DP。。
f[i][j][k]表示左上结束节点是第i条副对角线上的第j个点,右下结束节点是第n*2-i条副对角线上的第k个点,构成回文的方案数。
i那维滚动一下。时间复杂度O(n^3)空间复杂度O(n^2)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define ui unsigned int 7 using namespace std; 8 const int modd=1e9+7; 9 ui f[2][505][505]; 10 char mp[505][505],s[505][505]; 11 int i,j,k,n,m; 12 int ans; 13 14 int ra;char rx; 15 inline int read(){ 16 rx=getchar(),ra=0; 17 while(rx<‘0‘||rx>‘9‘)rx=getchar(); 18 while(rx>=‘0‘&&rx<=‘9‘)ra*=10,ra+=rx-48,rx=getchar();return ra; 19 } 20 21 int main(){ 22 n=read(); 23 for(i=1;i<=n;i++)scanf("%s",s[i]+1); 24 if(s[1][1]!=s[n][n]){puts("0");return 0;} 25 for(i=1;i<=n+n-1;i++) 26 for(j=1;j<=min(i,n+n-i);j++) 27 if(i<=n)mp[i][j]=s[i-j+1][j]; 28 else mp[i][j]=s[n-j+1][i+j-n]; 29 bool now=1,pre=0;int nn=n+n; 30 f[0][1][1]=s[1][1]==s[n][n]; 31 for(i=2;i<=n;i++,swap(now,pre)) 32 for(j=1;j<=i;j++)for(k=1;k<=i;k++)if(mp[i][j]==mp[nn-i][k]) 33 f[now][j][k]=(f[pre][j-1][k-1]+f[pre][j-1][k]+f[pre][j][k-1]+f[pre][j][k])%modd; 34 else f[now][j][k]=0; 35 for(i=1;i<=n;i++)ans+=f[pre][i][i],ans-=ans>=modd?modd:0; 36 printf("%d\n",ans); 37 }
时间: 2024-10-22 10:00:45