首页 > 其他分享 >CF 570E - Pig and Palindromes

CF 570E - Pig and Palindromes

时间:2023-06-10 15:22:41浏览次数:46  
标签:Palindromes int CF indx y1 x2 570E x1 dp

https://codeforces.com/problemset/problem/570/E
双向DP,类似于摘樱桃:https://leetcode.cn/problems/cherry-pickup/
记忆化搜索,超内存

#include <vector>
#include <string>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
	int n, m, MOD = 1e9+7;

	cin >> n >> m;
	vector<string> g(n);
	for(auto &s:g)
		cin >> s;

	vector<vector<vector<int>>> dp((n+m)/2, vector<vector<int>>(n, vector<int>(n, -1)));
	vector<vector<int>> dir = {{0,0}, {0,-1}, {1,-1}, {1,0}};

	function<int(int, int, int)> ms = [&](int k, int x1, int x2)
	{
		int y1 = k-x1, y2 = m-1-(k - (n-1-x2));
		if(x1 >= n || y1 >= m || x2 < 0 || y2 < 0)
			return -1;

		if(g[x1][y1] != g[x2][y2])
			return dp[k][x1][x2] = 0;
		if(dp[k][x1][x2] != -1)
			return dp[k][x1][x2];

		// 递归基
		if((n+m)%2 && 2*k+1 == m+n-2) // n+m奇数
			return dp[k][x1][x2] = (abs(x1-x2)+abs(y1-y2) == 1 ? 1 : 0);
		else if((n+m)%2==0 && 2*k == m+n-2) // n+m偶数
			return dp[k][x1][x2] = (x1==x2 && y1==y2);

		long long res = 0;

		for(auto &d:dir)
			res = (res + max(0, ms(k+1, x1+d[0], x2+d[1])))%MOD;

		return dp[k][x1][x2] = res;
	};
	cout << ms(0, 0, n-1);
	return 0;
}

改编出的滚动数组版本的dp,通过

#include <vector>
#include <string>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
	int n, m, MOD = 1e9+7;

	cin >> n >> m;
	vector<string> g(n);
	for(auto &s:g)
		cin >> s;

	vector<vector<vector<int>>> dp(2, vector<vector<int>>(n+1, vector<int>(n+1, 0)));

	int k = (n+m)%2 ? (m+n-3)/2 : (m+n-4)/2+1;
	bool indx = false;
	for(int x1 = 0; x1 < n; ++x1)
	{
		int y1 = k-x1;
		if(y1 >= m || y1 < 0)
			continue;
		for(int x2 = n-1; x2 >= 0; --x2)
		{
			int y2 = m-1-(k - (n-1-x2));
			if(y2 >= m || y2 < 0 || x2 < x1 || y2 < y1)
				continue;
			
			dp[indx][x1][x2] = (g[x1][y1] == g[x2][y2]);
		}
	}

	indx = !indx;

	while(k--)
	{
		for(auto &p : dp[indx])
			fill(p.begin(), p.end(), 0);
		for(int x1 = 0; x1 < n; ++x1)
		{
			int y1 = k-x1;
			if(y1 >= m || y1 < 0)
				continue;
			for(int x2 = n-1; x2 >= 0; --x2)
			{
				int y2 = m-1-(k - (n-1-x2));
				if(y2 >= m || y2 < 0 || x2 < x1 || y2 < y1 || g[x1][y1] != g[x2][y2])
					continue;
				
				dp[indx][x1][x2] = (dp[indx][x1][x2] + dp[!indx][x1][x2])%MOD;
				dp[indx][x1][x2] = (dp[indx][x1][x2] + dp[!indx][x1+1][x2])%MOD;
				dp[indx][x1][x2] = (dp[indx][x1][x2] + (x2-1 >= 0 ? dp[!indx][x1][x2-1] : 0))%MOD;
				dp[indx][x1][x2] = (dp[indx][x1][x2] + (x2-1 >= 0 ? dp[!indx][x1+1][x2-1] : 0))%MOD;
			}
		}
		indx = !indx;
	}
	indx = !indx;
	cout << dp[indx][0][n-1];
	return 0;
}

标签:Palindromes,int,CF,indx,y1,x2,570E,x1,dp
From: https://www.cnblogs.com/hellozhangjz/p/17471320.html

相关文章

  • CF437E The Child and Polygon
    TheChildandPolygon题解这世界这么大,遇到了这个奇奇怪怪的题。这道题其实可以很自然的联想到卡特兰数。在卡特兰数的计数中,有这么一个意义:\(C_n\)表示把有\(n+2\)条边的凸多边形分成\(n\)个三角形的方案数。利用这个意义可以得到\(C_n\)的另一个递推关系:\[C_n=......
  • CF1838A-Blackboard-List
    题意简述在黑板上有两个数字,进行如下操作\(n-2\)次:每次在黑板上选择任意两个数,将两个数的差的绝对值写在黑板上。这样你会得到一个长度为\(n(3\len\le100)\)的序列。一共\(t(1\let\le100)\)组数据。每组数据给定操作后的序列,需要你还原出最初写在黑板上的......
  • 「解题报告」CF1662J Training Camp
    模拟赛题,数据水被dfs草过去了。我们可以把每个点分成两个点\(a_{i,j},b_{i,j}\),设这一行中选取的数为\(v\),那么对于一行内\(\gev\)的点选\(a\),大于\(v\)的点选\(b\),那么题目的限制相当于每个点只能够选一个颜色。看起来就像网络流,考虑怎么转化到图上去。我们发现......
  • 第十一章--FCF中的基本数字格式
    时间:2009-01-1617:48   作者:道长A喜欢本页内容吗?那就收藏到您的博客吧。如果您有以下书签网站的账号,点击它即可收藏。谢谢您的支持!CSDNIEQQ百度POCOYahoo新浪365Key天极和讯博拉Live......
  • CF547E Mike and Friends题解
    题目链接温馨提示:做本题之前可以先尝试这个:洛谷P2414阿狸的打字机(是简单版的uwu)。首先,这个题涉及多模式串匹配,首先想AC自动机。但是有个问题:我们如何去计算一个串出现的次数呢?我们先考虑查询一个串\(a\)在串\(b\)中出现的次数。首先,在AC自动机上有一个性质,就是如果......
  • CF323B - Tournament-Graph
    题意:构造一个\(n\)大小的锦标赛图,即每两点之间恰有一条有向边,满足任意点对\((u,v)\),都存在一条从\(u\)到\(v\),长度不超过\(2\)的路径。方法一考虑奇数情况,假设我们的点是在环上排列的,那么我们对任意的跨越不超过半个环的边都连上,也就是说,我们把点看成圆上的若干个等分点......
  • CF1338 Div.1 做题记录
    ACF题面假定用到的最大的数是\(x\),那么一个数最大可以增大\(2^x-1\)。题目只要求不降,所以求出将\(a_i<a_{i-1}\)变成\(a_i=a_{i-1}\)时需要增大的最大值。求出这个数的二进制位数即可。点击查看代码#include<bits/stdc++.h>#defineullunsignedlonglong#definell......
  • 「解题报告」CF1290F Making Shapes
    最近好像一直懒得写题解,但是感觉还是写一写比较好。首先若干个向量组成一个凸包有经典做法,就是把向量按照极角排序,然后按照极角顺序依次拼接,得到的就是一个凸包,且方案唯一(由于本题限制不存在共线的两个向量)。那么我们实际上只需要知道每个向量最终用了多少就可以了。设第\(i\)......
  • DCFW SNAT
    #要先有个默认路由。#安全策略。#nat。#通了。......
  • CF1559D2 Mocha and Diana (Hard Version) 题解
    Luogu|Codeforces题意给定两个森林\(A\)和\(B\),均有编号\(1\)到\(n\)的节点,边数分别为\(m_1,m_2\)。现在进行加边操作,但是有两个要求:如果在第一个森林加一条\((u,v)\)的边,第二个森林也要进行同样的操作。反之同理。加边后两个森林依旧是森林。一棵树也是森林。......