三维dp 找对应步数的组合数目 二三维分别表示离1,1 和 n,m该步数的回文种类 如果吧状态数都存下内存太大 开个滚动dp数组(最近刚学的)
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#define mod 1000000007
#define ll long long
using namespace std;
char str[501][502];
ll dp[2][501][501];
int main()
{
int n,m,sp,i,e,j,k,y1,y2;
ll ans;
scanf("%d %d",&n,&m);
for(i = 1; i <= n; ++i) scanf("%s",str[i]+1);
if(str[1][1] != str[n][m])
{
puts("0");
return 0;
}
dp[0][1][n] = 1;
sp = n+m-2>>1;
for(e = 1,i = 1; i <= sp; ++i, e ^= 1)
{
memset(dp[e],0,sizeof(dp[e]));
for(j = 1; j <= min(i+1,n); ++j)
for(k = n; k >= j && k >= max(n-i,1); --k)
{
y1 = i+2-j, y2 = m-i+n-k;
if(str[j][y1] != str[k][y2]) continue;
dp[e][j][k] = (dp[e^1][j-1][k] + dp[e^1][j][k+1] + dp[e^1][j-1][k+1]+dp[e^1][j][k])%mod;
}
}
ans = 0;
e ^= 1;
if(n+m&1)
{
for(i = 1; i <= n; ++i) ans = (ans+dp[e][i][i]+dp[e][i][i+1])%mod;
}
else
{
for(i = 1; i <= n; ++i) ans = (ans+dp[e][i][i])%mod;
}
printf("%lld\n",ans);
return 0;
}