Codeforces 570E Pig and Palindromes dp

链接

题解链接:点击打开链接

题意:

给定n*m的字母矩阵。

从左上角到右下角的路径中有多少条是回文。

思路:

显然是要从头尾同时dp的,路径1是从左上角到第j行,路径2是从右下角到第k行

dp[i][j][k] 表示路径长度为i,路径1从左上角到第j行,路径2从右下角到第k行,且路径1和2是匹配的方法数。

对于路径1、2合并时要分一下奇偶。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <vector>
#include <string>
#include <time.h>
#include <math.h>
#include <iomanip>
#include <queue>
#include <stack>
#include <set>
#include <map>
const int inf = 1e9;
const double eps = 1e-8;
const double pi = acos(-1.0);
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x < 0) { putchar('-'); x = -x; }
	if (x > 9) pt(x / 10);
	putchar(x % 10 + '0');
}
using namespace std;
const int N = 520;
const int mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> pii;
void add(int &x, int y) {
	x += y;
	if (x >= mod)x -= mod;
}
int mul(int x, int y) {
	x = (ll)x*y%mod;
	return x;
}
int n, m;
char s[N][N];
vector<pii>G[1005];
int step[4][2] = { 0, 1, 1, 0, 0, -1, -1, 0 }, dis[N][N];
bool inmap(int x, int y) {
	return 1 <= x&&x <= n && 1 <= y&&y <= m;
}
void bfs() {
	queue<int>qx, qy;
	qx.push(1); qy.push(1);
	dis[1][1] = 1;
	while (!qx.empty()) {
		int ux = qx.front(), uy = qy.front();
		G[dis[ux][uy]].push_back({ ux, uy });
		qx.pop(); qy.pop();
		for (int i = 0; i < 2; i++) {
			int vx = ux + step[i][0], vy = uy + step[i][1];
			if (inmap(vx, vy) && !dis[vx][vy]) {
				dis[vx][vy] = dis[ux][uy] + 1;
				qx.push(vx); qy.push(vy);
			}
		}
	}
}
int dp[2][N][N];
int main() {
	rd(n); rd(m);
	for (int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
	if (s[1][1] != s[n][m]) { puts("0"); return 0; }
	s[0][1] = 'a'; s[1][0] = 'z' + 1;
	s[n + 1][m] = 'a'; s[n][m + 1] = 'z' + 1;
	bfs();
	int cur = 0, old = 1;
	memset(dp[cur], 0, sizeof dp[cur]);
	dp[cur][1][n] = 1;
	int l = 1, r = n + m - 1;
	for (int i = 2; i <= (n + m) / 2; i++, l++, r--)
	{
		swap(cur, old);
		memset(dp[cur], 0, sizeof dp[cur]);
		for (auto u : G[l])
		{
			int x = u.first, y = u.second;
			for (auto v : G[r])
			{
				int tx = v.first, ty = v.second;
				if (dp[old][x][tx] == 0)continue;
				for (int a = 0; a < 2; a++)
				{
					int ux = x + step[a][0], uy = y + step[a][1];
					if (!inmap(ux, uy))continue;
					for (int b = 2; b < 4; b++)
					{
						int vx = tx + step[b][0], vy = ty + step[b][1];
						if (!inmap(vx, vy))continue;
						if (s[ux][uy] != s[vx][vy])continue;

						add(dp[cur][ux][vx], dp[old][x][tx]);
					}
				}
			}
		}
	}
	int ans = 0;
	if ((n + m) & 1)
	{
		for (int i = 1; i <= n; i++)
			add(ans, dp[cur][i][i]);
		for (int i = 1; i <= n; i++)
			add(ans, dp[cur][i][i + 1]);
	}
	else {
		for (int i = 1; i <= n; i++)
			add(ans, dp[cur][i][i]);
	}
	pt(ans);
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 02:33:02

Codeforces 570E Pig and Palindromes dp的相关文章

【动态规划】Codeforces 570E Pig and Palindromes

通道 题意:n*m的字符矩阵,每次只能向右或向下走,求从(1,1)走到(n,m)的路径中有多少个回文. 思路:我们可以从两端开始走.dp[i][j][k]:分别走i步(也可以理解为半径为i),A到达j行,B到达k行的回文数.走的半径逐渐减少即可. 可以知道第x1行只能由前一次的x1行或x1+1行转移,第x2行只能由前一次的x2-1或x2转移,所有就有四种情况. dp[i][x1][x2] = (dp[i-1][x1][x2] + dp[i-1][x1 + 1][x2] + dp[i-1][x1]

Codeforces #316 E Pig and Palindromes DP

// Codeforces #316 E Pig and Palindromes // // 题目大意: // // 给你一张地图,n*m每个点是一个字母,现在从(0,0)出发, // 每次只能往右或者往下走,求走到(n-1,m-1)形成回文串的方法数. // // 解题思路: // // 动态规划.首先.如果起点和终点的字母不相同,那么肯定 // 不能形成回文串,直接输出0.对于能形成回文串.我们设状态 // d(step,i,j)表示走了step步,从第0行走到i行,第n-1行走到j行的 /

Codeforces Round #316 (Div. 2)E. Pig and Palindromes DP

E. Pig and Palindromes Peppa the Pig was walking and walked into the forest. What a strange coincidence! The forest has the shape of a rectangle, consisting of n rows and m columns. We enumerate the rows of the rectangle from top to bottom with numbe

codeforces 570 E. Pig and Palindromes (DP)

题目链接: 570 E. Pig and Palindromes 题目描述: 有一个n*m的矩阵,每个小格子里面都有一个字母.Peppa the Pig想要从(1,1)到(n, m).因为Peppa the Pig是一个完美主义者,她想要她所经过的路径上的字母组成的字符串是一个回文串,现在Peppa the Pig想要知道有多少满足条件的走法? 解题思路: 因为经过路径上的字母要组成回文串,所以可以从(1,1),(n,m)同时开始dp.从(1,1)出发只能向下方和右方走,从(n,m)出发只能向上

CF 316div2 E.Pig and Palindromes

E. Pig and Palindromes Peppa the Pig was walking and walked into the forest. What a strange coincidence! The forest has the shape of a rectangle, consisting of n rows and m columns. We enumerate the rows of the rectangle from top to bottom with numbe

Codeforces 360C Levko and Strings dp

题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t对应位置的k个子串字典序>s #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #

CodeForces 30C Shooting Gallery 简单dp

题目链接:点击打开链接 给定n个气球 下面n行 x y t val 表示气球出现的坐标(x,y) 出现的时刻t,气球的价值val 枪每秒移动1个单位的距离 问: 射击的最大价值,开始时枪瞄准的位置任意. 思路: dp一下.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include