题目链接:
题目描述:
有一个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 "); 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 ", ans); 65 66 } 67 return 0; 68 }