hdoj 5617 Jam's maze(滚动数组dp求回文数)

Jam's maze


Problem Description
Jam got into a maze, he has to find a palindrome path from  (1,1) to  (N,N) to get out.
However he is not only thinking about how to get out of the maze,
but also counting the number of ways he can get out.

The maze a  NN grid. On each cell is a uppercase letter.
Jam is at upper-left corner  (1,1) now, and the exit is at lower-right corner  (N,N).
Jam can only go down or go right.
Considering the number of palindrome path may be huge, you just need to output the number mod  5201314.
 

Input
The first line is  T(1T10) means  T Case.
For each case:
The first line is  N(1N500) means the size of the maze.
Then  N lines follow, each line has  N uppercase letter.
 

Output
For each testcase, output the number of palindrome path mod  5201314.
 

Sample Input
   
   
   
   
1 4 ABCD BEFE CDEB GCBA
 

Sample Output
   
   
   
   
12
Hint
there are 1 solutions is"ABCDCBA" there are 1 solutions is"ABCGCBA" there are 4 solutions is"ABEDEBA" there are 6 solutions is"ABEFEBA"
 

Source
BestCoder Round #70



这道题考虑的是回文串,有人会想到后缀数组自动机马拉车什么的,其实只要求方案数很多,所以我们应该想到动态规划,首先是状态的定义,我们可以想着从 (1,1)(1,1) (n,n)(n,n) 开始走,然后走到相遇。所以我们定义状态可以定义为 f[x_1][y_1][x_2][y_2]f[x1][y1][x2][y2] 表示所对应的两个点 (x_1,y_1)(x_2,y_2)(x1,y1)(x2,y2) ,这样的话考虑到数据的范围,显然会爆空间,然后我们想一想就是走多少步和知道 x_1,x_2x1,x2 的位置,就可以确定 y_1,y_2y1,y2 的位置。于是我们把状态定义为 f[i][x_1][x_2]f[i][x1][x2

]即可,状态转移很显然,如果相等的话把四个方向都扫一下即可。因为还是会爆空间,所以我们把第一维改成滚动数组就解决问题

#include<cstdio>
#include<cstring>
using namespace std;
const int MOD=5201314;
const int maxn=500+5;
char s[maxn][maxn];
int dp[2][maxn][maxn];
void add(int &x,int y)
{
    x+=y;
    if(x>=MOD)
        x-=MOD;
}
int main()
{
    int T,n,i,x1,x2,y1,y2;
    scanf("%d",&T);
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%s",s[i]+1);
        if(s[n][n]!=s[1][1])
        {
            printf("0\n");
            continue;
        }
        int step=n-1;
        int op=0;
        dp[0][1][n]=1;
        for(i=1;i<=step;i++)
        {
            memset(dp[!op],0,sizeof(dp[!op]));
            for(x1=1;x1<=i+1;x1++)
                for(x2=n;x2>=n-i;x2--)
                {
                    if(x1>x2)
                        continue;
                    y1=i+2-x1;
                    y2=n*2-x2-i;
                    if(s[x1][y1]==s[x2][y2])
                    {
                        add(dp[!op][x1][x2],dp[op][x1][x2+1]);
                        add(dp[!op][x1][x2],dp[op][x1][x2]);
                        add(dp[!op][x1][x2],dp[op][x1-1][x2]);
                        add(dp[!op][x1][x2],dp[op][x1-1][x2+1]);
                    }
                }
            op=!op;
        }
        int ans=0;
        for(i=1;i<=n;i++)
            add(ans,dp[op][i][i]);
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(hdoj 5617 Jam's maze(滚动数组dp求回文数))