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)出发只能向上方和左方走。然后就可以dp[x1][y1][x2][y2],其实呢可以把dp数组优化到三维dp[step][x1][x2]。因为从两点出发走过的步数是一样的,知道了走过的步数和一个方向的坐标,就可以求出另一个方向的坐标咯。但是酱紫搞的话,还是会MTL的(亲身经历>_<)······,但是请我们尊贵的滚动数组出场就一切ok咯。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 const int maxn = 510;
 5 const int mod = 1000000007;
 6 int dp[2][maxn][maxn], n ,m;
 7 char maps[maxn][maxn];
 8
 9 int main ()
10 {
11     while (scanf ("%d %d", &n, &m) != EOF)
12     {
13         for (int i=1; i<=n; i++)
14             scanf ("%s", maps[i]+1);
15
16         if (maps[1][1] != maps[n][m])
17         {
18             printf ("0\n");
19             continue;
20         }
21
22         memset (dp, 0, sizeof(dp));
23         dp[0][1][n] = 1;
24         int res = (n + m - 2) / 2;
25
26         for (int i=1; i<=res; i++)
27         {
28             for (int j=1; j<=i+1; j++)
29                 for (int k=n; k>=n-i; k--)
30                 {
31                     int x1, x2, y1, y2;
32                     x1 = j, y1 = i - j + 2;
33                     x2 = k, y2 = n + m - k - i;
34
35                     if (maps[x1][y1] == maps[x2][y2])
36                     {
37                         if (x1>x2 || y1>y2)
38                             continue;
39                         dp[i%2][j][k] = (dp[i%2][j][k] + dp[(i%2)^1][j-1][k])%mod;
40                         dp[i%2][j][k] = (dp[i%2][j][k] + dp[(i%2)^1][j-1][k+1])%mod;
41                         dp[i%2][j][k] = (dp[i%2][j][k] + dp[(i%2)^1][j][k])%mod;
42                         dp[i%2][j][k] = (dp[i%2][j][k] + dp[(i%2)^1][j][k+1])%mod;
43                     }
44
45                 }
46             memset(dp[(i%2)^1], 0, sizeof(dp[(i%2)^1]));
47         }
48
49         int ans = 0;
50         if ((n+m)%2 == 0)
51         {
52             for (int i=1; i<=n; i++)
53                 ans = (ans + dp[res%2][i][i]) % mod;
54         }
55         else
56             for (int i=1; i<=n; i++)
57             {
58                 int x = res - i + 2;
59                 if (x + 1 <= m)
60                     ans = (ans + dp[res%2][i][i]) % mod;
61                 if (i + 1 <= n)
62                     ans = (ans + dp[res%2][i][i+1]) % mod;
63             }
64         printf ("%d\n", ans);
65
66     }
67     return 0;
68 }
时间: 2024-10-07 01:21:34

codeforces 570 E. Pig and Palindromes (DP)的相关文章

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 570 E. Pig and Palindromes

题意:给出n*m的字母表,求从左上角走到右下角能形成多少个回文串,只能往下或往右走. 做法:dp[r1][c1][r2][c2],从左上角走到(r1,c1),从右下角走到(r2,c2)时,能形成多少个回文串,因为爆内存,表示成dp[step][r1][r2],从左上角走到r1行,从右下角走到r2行,分别走了step步时,能形成多少个回文串,因为c1=step+2-r1,c2=n+m-step-r2,所以是一样的,这样差不多能过了,因为两边最多走250步,所以需要的空间是250*500*500,当

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 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 <std

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 540D Bad Luck Island 概率dp

CodeForces 540D 应该是简单概率dp,由于写得少显得十分蠢萌 求期望逆推,求概率正推,大概是这么个意思,贴一发留恋 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define db double const int maxn=108; db dp[maxn][maxn][maxn]; int main() { int i,j,n,m,k,p; whi

codeforces 148E Aragorn&#39;s Story 背包DP

Aragorn's Story Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/148/E Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who

CodeForces 21D Traveling Graph 状压dp+欧拉回路

题目链接:点击打开链接 题意: 给定n个点m条边的无向图 求从1点开始经过每条边至少一次最后回到1点的最小路程 显然就是找一条路径可重复的欧拉回路 思路: 首先对于欧拉回路的结论是:所有点的度数都为偶数 因为所有边至少经过一次,那么可以把题意转换成加最少多少条边使得图满足以上结论 而加的边目的是为了把奇度数转成偶度数,先floyd一下得到任意点间加边的最小花费 dp[i]表示状态i下度数都为偶数的最小花费. 状压dp,把i状态下,所有未选择的点中挑2个奇度数的转移即可. #include <cs

Codeforces 67C Sequence of Balls 编辑距离 dp

题目链接:点击打开链接 有一个交换操作比较特殊,所以记录每个点距离自己最近的那个字符的位置 然后交换就相当于把第一行要交换的2个字符 之间的字符都删掉 把第二行要交换的2个字符 之间的字符都插入第一行的2个字符之间 然后再进行交换. #include <cstdio> #include <cstring> #include<iostream> using namespace std; #define inf 10000000 #define N 4005 #define