1. 程式人生 > >luogu 3126 回文的路徑

luogu 3126 回文的路徑

-i scan nbsp long 相同 scanf include int put

https://www.luogu.org/problem/show?pid=3126

考慮dp,從兩頭走到中間。

f[i][j][k][l]表示從左上角走到(i,j),從右下角走到(k,l),路徑長度相等,所經過路徑相同的方案數。

方程不再贅述。

考慮步數要相同,所以只要枚舉步數和行就好。

f[i][j][k]表示第一個點在第j行,第2個點在第k行,走i步的方案數。

所以得出方程f[i][j][k]=(f[i-1][j-1][k]+f[i-1][j][k+1]+f[i-1][j-1][k+1]+f[i-1][j][k])%mod;

然後顯然第一維滾動數組優化。

#include<cstdio>
#include
<cstring> #define clz 1000000007 int n,m; long long f[2][510][510]; char s[510][510]; int Max(int a,int b){ return a>b?a:b; } int Min(int a,int b){ return a<b?a:b; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%s",s[i]+1); } if(s[1][1]!=s[n][m]) return
!puts("0"); f[0][1][n]=1; bool I=1; for(int i=1;i<=(n+m-2)>>1;i++){ memset(f[I],0,sizeof(f[I])); for(int j=1;j<=Min(i+1,n);j++){ for(int k=n;k>=j&&k>=Max(n-i,1);k--){ int p1=i-j+2,p2=m-i+n-k; if(s[j][p1]==s[k][p2]){ f[I][j][k]
=(f[I^1][j-1][k]+f[I^1][j][k+1]+f[I^1][j-1][k+1]+f[I^1][j][k])%clz; } } } I^=1; } long long ans=0; I^=1; if((n+m)%2==1){ for(int i=1;i<=n;i++) ans=(ans+f[I][i][i]+f[I][i][i+1])%clz; } else{ for(int i=1;i<=n;i++) ans=(ans+f[I][i][i])%clz; } printf("%lld\n",ans%clz); return 0; }

luogu 3126 回文的路徑