HDU 5617 Jam's maze(dp)

来源:互联网 发布:矩阵防御 编辑:程序博客网 时间:2024/06/06 03:57

Description
Jam走进了一个迷宫,他要想走出这个迷宫,必须找到一条路径,使得这条路径是回文的,当然他可不屑于去走出这个迷宫,聪明的他一定要找出有多少种方案走出这个迷宫。在一个N*N大小的迷宫,这个迷宫全由大写字母组成,他会从左上角走到右下角,然后把所有经过的字符连成一个串,当然只能往下和往右走,问有多少种方案可以走出来,当然答案会很大,所以答案和5201314取模输出
Input
第一行T(1≤T≤10),表示T组数据。
接下来T组数据:
每组数据第一行为N(1≤N≤500)表示矩阵的行和列
接下来N行N列N*N个字符
Output
输出合法方案数
Sample Input
1
4
ABCD
BEFE
CDEB
GCBA
Sample Output
12
Solution
一个人从(1,1)走了一个回文串到(n,n)其实就是两个人分别从(1,1)和(n,n)出发走了相同的字符串最后相遇,用dp[step][x1][y1][x2][y2]表示走了step步,第一个人走到(x1,y1)点,第二个人走到了(x2,y2)点,且两人走过的字符串完全相同的方案数,那么有
dp[step][x1][y1][x2][y2]+=dp[step-1][x1-1][y1][x2+1][y2]
dp[step][x1][y1][x2][y2]+=dp[step-1][x1][y1-1][x2+1][y2]
dp[step][x1][y1][x2][y2]+=dp[step-1][x1][y1-1][x2][y2+1]
dp[step][x1][y1][x2][y2]+=dp[step-1][x1-1][y1][x2][y2+1]
考虑到空间太大所以要优化一下,首先第一维可以滚动一下,然后发现step确定时,y1和y2可以由x1和x2确定,故只需要开三维即可
Code

#include<cstdio>#include<iostream>#include<cstring>using namespace std;typedef long long ll;#define mod 5201314#define maxn 555int T,n,dp[2][maxn][maxn];char m[maxn][maxn];int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        for(int i=1;i<=n;i++)scanf("%s",m[i]+1);        memset(dp,0,sizeof(dp));        int cur=0;        dp[0][1][n]=(m[1][1]==m[n][n]);        for(int i=1;i<n;i++)        {            memset(dp[cur^1],0,sizeof(dp[cur^1]));            for(int x1=1;x1<=i+1;x1++)                for(int x2=n;x2>=n-i;x2--)                {                    int y1=i+2-x1,y2=2*n-i-x2;                    if(m[x1][y1]!=m[x2][y2])continue;                    dp[cur^1][x1][x2]=(dp[cur^1][x1][x2]+dp[cur][x1][x2])%mod;                    dp[cur^1][x1][x2]=(dp[cur^1][x1][x2]+dp[cur][x1][x2+1])%mod;                    dp[cur^1][x1][x2]=(dp[cur^1][x1][x2]+dp[cur][x1-1][x2])%mod;                    dp[cur^1][x1][x2]=(dp[cur^1][x1][x2]+dp[cur][x1-1][x2+1])%mod;                }            cur^=1;        }        int ans=0;        for(int i=1;i<=n;i++)ans=(ans+dp[cur][i][i])%mod;        printf("%d\n",ans);    }    return 0;}
0 0