首页 > 其他分享 >暑假专题训练 dp 2023-7-26

暑假专题训练 dp 2023-7-26

时间:2023-07-27 20:48:09浏览次数:48  
标签:26 int dg typedef wall 2023 pair include dp

L. Hamiltonian Wall


算法:dp

做法:由于要一笔将所有黑块都划出来。所以我们状态转移方程应尽可能从左上角或者右下角的黑方块转移过来。$$f[i,j] = f[i, j - 1] + 1 \ (wall[i,j - 1] = B, w[i, j] = B)$$ $$f[i][j] = f[i + 1][j - 1] + 2 \ (i == 1,wall[i + 1][j - 1] == B,wall[i + 1][j] == B)$$ $$f[i][j] = f[i - 1][j - 1] + 2 \ (i == 2,wall[i - 1][j - 1] == B,wall[i - 1][j] == B)$$

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define fir first
#define sec second
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 200010;

int m;
char wall[3][N];
int f[3][N];

void solve()
{
	cin >> m;
	int cnt = 0;
	wall[1][0] = 'B', wall[2][0] = 'B';
	for (int i = 1; i <= 2; i++)
		for (int j = 0; j <= m; j++)
			f[i][j] = 0;

	for (int i = 1; i <= 2; i++)scanf("%s", wall[i] + 1);
	for (int i = 1; i <= 2; i++)
		for (int j = 1; j <= m; j++)
			if (wall[i][j] == 'B')cnt++;

	for (int j = 1; j <= m; j++)
	{
		for (int i = 1; i <= 2; i++)
		{
			if (wall[i][j] == 'B')
			{
				if (wall[i][j - 1] == 'B')f[i][j] = f[i][j - 1] + 1;
				if (i == 1 && wall[i + 1][j - 1] == 'B' && wall[i + 1][j] == 'B')f[i][j] = f[i + 1][j - 1] + 2;
				if (i == 2 && wall[i - 1][j - 1] == 'B' && wall[i - 1][j] == 'B')f[i][j] = f[i - 1][j - 1] + 2;
			}
		}
	}

	if (f[1][m] == cnt || f[2][m] == cnt)cout << "YES" << endl;
	else cout << "NO" << endl;
}

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}

	return 0;
}

 

K. Living Sequence


算法:数位dp+二分或者是构造(这里只写构造)

做法:考虑每一个数的一个数位如果出现4,那么就删去,这说明十进制的数少了一个数,变成了九进制。即九进制0、1、2、3、4、5、6、7、8可以变成0、1、2、3、5、6、7、8、9。题目中的k为十进制中去掉4的第几位数,那么就相当于每一个数位都是0、1、2、3、5、6、7、8、9这样的九进制。那么把k转化为九进制为dg,随后对dg的每一位进行判断,小于4就说明没有跳过4000...这样的数。大于等于4就说明有跳过4000...这样的数,那么这个数位要加1

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define fir first
#define sec second
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 200010;

LL k;

void solve()
{
	cin >> k;
	vector<int> dg;
	while (k)dg.push_back(k % 9), k /= 9;
	reverse(dg.begin(), dg.end());
	
	for (int i = 0; i < dg.size(); i++)
	{
		if (dg[i] < 4)cout << dg[i];
		else cout << dg[i] + 1;
	}
	cout << endl;
}

int main()
{
    ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}

	return 0;
}

 

A. Matching


算法:状态压缩dp

做法:
f[i][j]第一维表示男生与女生的匹配个数,第二维表示男女生的匹配关系。
注意i个男生和女生的各种关系的匹配的方案数是从i - 1个男生和女生的各种关系的匹配的方案数转移过来的。
 由于最终我们要找的是每一个男生都要与一个女生成一对的方案数(每个男生或女生都只能出现在一对关系中)。
 那么我们可以这样想,1 -- ii个男生,那么必定要有i个女生,我们预处理出所有1的个数为i( \(1 <= i <= n\) )的且大小不超过(1 << n) - 1的数,这些数存入vector数组w[n + 1]中。 枚举到i的时候,我们从有i1的数中遍历且设该数为p,如果这个第i个男生对第j( \(0 <= j < n\) )个女生有好感,即初始输入的数组中 \(a_{i,j - 1} = 1\),那么我们再判断p右移j位是否也是1,是的话我们将这个1减去,得到的数必定1的数量比先前少1个,即i - 1。那么我们当前i个男生和i个女生的匹配关系的式子是f[i][p]
 那么我们就可以有f[i][p] = ((LL)f[i][p] + f[i - 1][q]) % mod, 且q = p - (1 << j)(减去一个1后的匹配关系),表示上一次i - 1个男生在与i - 1个女生按q的关系匹配的数量加到目前i个男生和i个女生的匹配关系为p的方案数中。

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define fir first
#define sec second
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

const int N = 22, M = 1 << 21, mod = 1e9 + 7;

int n;
int g[N][N];
int f[N][M];
vector<int> w[23];

int count(int x)
{
	int cnt = 0;
	for (int j = 0; j < n; j++)
		if ((x >> j) & 1)cnt++;
	return cnt;
}

void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 0; j < n; j++)
			cin >> g[i][j];

	for (int i = 0; i < (1 << n); i++)
	{
		int cnt = count(i);
		w[cnt].push_back(i);
	}

	f[0][0] = 1;
	for (int i = 1; i <= n; i++)
	{
		for (auto p : w[i])
		{
			for (int j = 0; j < n; j++)
			{
				if (g[i][j] && ((p >> j) & 1))
				{
					int q = p - (1 << j);
					f[i][p] = ((LL)f[i][p] + f[i - 1][q]) % mod;
				}
			}
		}
	}

	cout << f[n][(1 << n) - 1];
}

int main()
{
    ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	solve();

	return 0;
}

 

E. ConstructOR


算法:构造

做法:我们先求出a | b的值,设为k。判断k的二进制的最小的一位1是否比d的二进制的最小的一位1还要小,若是则不存在x。之后我们对于k值的二进制数从小到大遍历,只要当前的数位为1且我们所求的x的对应数位为0的话我们就加上d在左移若干位后的结果。左移的结果一定要保证其二进制数的最小的一位1的对应数位与k的对应数位相同,这样x加上这个值才能把0变成1

code
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <deque>
#include <cmath>
#include <string>
#include <set>
#define fir first
#define sec second
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, int> PDI;
typedef pair<double, double> PDD;
int dx[4] = { -1, 1, 0, 0 }, dy[4] = { 0, 0, -1, 1 };

LL a, b, d, c;

void solve()
{
	cin >> a >> b >> d;
	a = a | b, c = d;

	if ((a & (-a)) < (d & (-d)))
	{
		cout << -1 << endl;
		return;
	}

	vector<int> w;
	while (a)w.push_back(a % 2), a /= 2;

	int p = 0;
	while (c)
	{
		if (c & 1)break;
		c /= 2, p++;
	}

	LL x = 0;
	for (int i = 0; i < w.size(); i++)
	{
		if (w[i] == 1 && ((x >> i) & 1) == 0)
		{
			x += d << (i - p);
		}
	}

	cout << x << endl;
}

int main()
{
    ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}

	return 0;
}

标签:26,int,dg,typedef,wall,2023,pair,include,dp
From: https://www.cnblogs.com/dkdklcx/p/17584328.html

相关文章

  • ThreadPoolExecutor源码分析
    packagejava.util.concurrent;importjava.util.concurrent.locks.*;importjava.util.*;publicclassThreadPoolExecutorextendsAbstractExecutorService{/***runStateprovidesthemainlifecylecontrol,takingonvalues:**......
  • 20230727
    复赛树塔问题只需要知道\(f\left[i,j\right]\)是从\(f\left[i+1,j\right]\)还是\(f\left[i+1,j+1\right]\)转移来就可以,不需要知道\(f\left[i+1,j\right]\)和\(f\left[i+1,j+1\right]\)是怎么计算出的,这就是无后效性。......
  • wordpress 插件 woocommerce自定义订单信息验证
    使用php钩子函数增加自定义验证add_action('woocommerce_after_checkout_validation',function($fields){if($fields['billing_phone']&&!preg_match('/^((\+1|1)?(|-)?)?(\([2-9][0-9]{2}\)|[2-9][0-9]{2})(|-)?([2-9][0-9]{2}(|-)?[0-9......
  • 2023.7.27 周四:static
    1publicclassStudent{2privateintage;//非静态变量3privatestaticintscore;//静态变量4publicvoidrun(){56}7publicstaticvoidgo(){89}1011publicstaticvoidmain(String[]args){12Stud......
  • ETHERNET/IP转PROFIBUS-DP网关EtherNet/IP与Profibus DP通讯网关
    大家好,今天要给大家介绍一款非常神奇的通讯网关捷米特JM-DPM-EIP!这款产品可以将各种PROFIBUS-DP从站接入到ETHERNET/IP网络中,真是一款神奇的产品啊!你是否想过,如果没有这款产品,PROFIBUS-DP从站和ETHERNET/IP网络之间该怎么通讯呢?让我们来看看这款产品到底有哪些神奇之处吧! 这款......
  • 2023-7-27 WPF自定义命名空间在xaml中的使用
    xaml自定义命名空间【作者】长生为啥要用自定义命名空间这是常见的几种命名空间xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:Rxsfadsf"xmlns:s......
  • 2023-7-27WPF的ContextMenu的传参绑定方式
    WPF的ContextMenu的绑定方式【作者】长生ContextMenu为何不能正常绑定在wpf中ContextMenu和ToolTip一样都是弹出层,与VisualTree已经分离了,只不过ToolTip在wpf中有进行特殊处理,所以可以正常绑定。个人觉得ContextMenu绑定的最可靠的方式首先添加BindingProxy类,继承Freezab......
  • PhpStorm 2023 for Mac永久激活版下载(免登陆版)
    Phpstorm是一款由JetBrAIns开发的PHP集成开发环境(IDE)。它提供了许多功能来简化PHP应用程序开发,包括代码编辑、调试、代码分析、测试和版本控制等。PhpStorm2023forMac永久激活版下载 以下是Phpstorm的一些主要特点:代码编辑器:Phpstorm具有智能代码编辑器,支持语法高亮、代......
  • idea2023.1.3 最新激活教程
    说明本教程用来激活 idea2023.1.3版本。激活效果 下载idea2023.1.3版本客户端官网地址:https://www.jetbrains.com/idea/download/other.html根据自己所需下载相应的版本安装(解压)idea2023.1.3版本客户端解压版本的直接在自己的软件安装目录解压即可安装版本一路nex......
  • 行业追踪,2023-07-27
    自动复盘2023-07-27凡所有相,皆是虚妄。若见诸相非相,即见如来。k线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让市场来告诉你跟踪板块总结:成交额超过100亿排名靠前,macd柱由绿转红成交量要大于均线有必要给每个行......