题目
题意
给定一个n*m的字符矩阵,求从起点[1,1]走到终点[n,m]处是回文串的路线方案个数。(只可以向下走或者向右走)
思路
从起点和终点向中间搜索,dp[i][j][k]
表示分别走了i步,起点走到第j行终点走到第k行的方案数。然后就可以滚了233333
当总共步数是奇数时直接相加即可,偶数时则要判断最后两个字符是不是相同。
代码
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
const int mx = 505;
const ll mod = 1e9+7;
char chr[mx][mx];
ll dp[2][mx][mx];
int main(){
int n,m;
ll ans=0;
bool jud;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",chr[i]+1);
if(chr[1][1]!=chr[n][m])
puts("0");
else{
int p1,p2,p3,p4,t=0;
dp[0][1][n]=1;
if((m+n)%2) jud=true;
else jud=false;
for(int i=0;i<=(m+n-2)/2;i++){
memset(dp[t^1],0,sizeof(dp[t^1]));
for(int j=1;j<=n;j++){
for(int k=n;k>=1;k--){
if(n-k>i)continue;
p1=j;
p2=i-p1+2;
p3=k;
p4=m+n-i-k;
if(p1<=0||p1>n)continue;
if(p2<=0||p2>m)continue;
if(p3<=0||p3>n)continue;
if(p4<=0||p4>m)continue;
if(chr[p1][p2]==chr[p3][p4]){
dp[t^1][p1][p3]+=dp[t][p1][p3]+dp[t][p1][p3+1]+dp[t][p1-1][p3]+dp[t][p1-1][p3+1];
dp[t^1][p1][p3]%=mod;
}
}
}
t=t^1;
}
if(jud){
for(int i=1;i<=n;i++){
p1=(m+n-2)/2-i+2;
if(chr[i][p1]==chr[i][p1+1])
ans+=dp[t][i][i];
if(chr[i][p1]==chr[i+1][p1])
ans+=dp[t][i][i+1];
ans%=mod;
}
}
else{
for(int i=1;i<=n;i++){
ans+=dp[t][i][i];
ans%=mod;
}
}
printf("%I64d\n",ans%mod);
}
return 0;
}