题意:n*m的格子,每个格子上有一个字符,从(1,1)走到(n,m)只能向下和向右,问走过的字符串是回文的个数有多少
题解:比较容易想到是dp,dp[step][x1][y1][x2][y2],表示第step步到(x1,y1)和(x2,y2)共有多少种方案
但这样的话,时间空间都爆炸
可以用滚动数组优化掉一维,但空间还是会爆炸
其实,只要知道了step,知道了x1,x2,就可以求出y1,y2了
需要注意(x+y)是奇数的情况
int n,m;
char c[510][510];
LL dp[2][510][510];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
scanf("%s",c[i]+1);
}
int temp=0;
if(c[1][1]==c[n][m])
dp[temp][1][n]=1;
for(int step=1;step<=(n+m-2)/2;step++){
temp=temp^1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dp[temp][i][j]=0;
}
}
for(int x1=1;x1<=n && x1-1<=step;x1++){
for(int x2=n;x2>=1 && n-x2<=step;x2--){
int y1=step-x1+2;
int y2=m-(step-(n-x2));
if(c[x1][y1] != c[x2][y2]){
continue;
}
dp[temp][x1][x2]=(dp[temp][x1][x2]+dp[temp^1][x1][x2])%mod;
dp[temp][x1][x2]=(dp[temp][x1][x2]+dp[temp^1][x1][x2+1])%mod;
dp[temp][x1][x2]=(dp[temp][x1][x2]+dp[temp^1][x1-1][x2])%mod;
dp[temp][x1][x2]=(dp[temp][x1][x2]+dp[temp^1][x1-1][x2+1])%mod;
}
}
}
LL ans=0;
for(int i=1;i<=n;i++){
ans=(ans+dp[temp][i][i])%mod;
}
if((n+m)&1){
for(int i=1;i<n;i++){
ans=(ans+dp[temp][i][i+1])%mod;
}
}
cout<<ans<<endl;
return 0;
}