HDU 5617 DP

沿着一条条斜线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 }
View Code

 

posted @ 2016-01-31 21:10  活在夢裡  阅读(307)  评论(0编辑  收藏  举报