沿着一条条斜线DP即可,dp[k][i][j]表示第k步,一端在第j列,另一端在第i列,构成回文的个数,沿着四个方向推下去即可。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <cstring> 6 #include <cstdio> 7 #include <cmath> 8 #include <cstdlib> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 14 using namespace std; 15 16 const int N=505; 17 const int MOD=5201314; 18 char g[N][N]; 19 int dp[2][N][N]; 20 21 void add(int &a,int b) { 22 a+=b; 23 while (a>MOD) 24 a-=MOD; 25 } 26 int main () { 27 int T; 28 scanf("%d",&T); 29 while (T--) { 30 int n; 31 scanf("%d",&n); 32 for (int i=1;i<=n;i++) { 33 scanf("%s",g[i]+1); 34 for (int j=1;j<=n;j++) { 35 dp[0][i][j]=0; 36 dp[1][i][j]=0; 37 } 38 } 39 if (g[1][1]!=g[n][n]){ 40 puts("0"); 41 continue; 42 } 43 int s=0; 44 dp[s][1][n]=1; 45 int ret=0; 46 for (int k=2;k<=n;k++) { 47 s^=1; 48 for (int j1=1,i1=k;j1<=k;j1++,i1--) { 49 for (int j2=n,i2=n-k+1;j2>=n-k+1;j2--,i2++) { 50 dp[s][j1][j2]=0; 51 } 52 } 53 for (int j1=1,i1=k;j1<=k;j1++,i1--) { 54 for (int j2=n,i2=n-k+1;j2>=n-k+1;j2--,i2++) { 55 if (g[i1][j1]!=g[i2][j2]) continue; 56 add(dp[s][j1][j2],dp[s^1][j1][j2]); 57 add(dp[s][j1][j2],dp[s^1][j1-1][j2]); 58 add(dp[s][j1][j2],dp[s^1][j1-1][j2+1]); 59 add(dp[s][j1][j2],dp[s^1][j1][j2+1]); 60 } 61 } 62 } 63 for (int j=1;j<=n;j++) 64 add(ret,dp[s][j][j]); 65 printf("%d\n",ret); 66 } 67 return 0; 68 }
时间: 2024-11-06 19:22:19