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 555
int 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;
}