[USACO15OPEN]回文的路径Palindromic Paths 2.0版
题目描述
农夫FJ的农场是一个N*N的正方形矩阵(2\le N\le 5002≤N≤500),每一块用一个字母作标记。比如说:
ABCD
BXZX
CDXB
WCBA
某一天,FJ从农场的左上角走到右下角,当然啦,每次他只能往右或者往下走一格。FJ把他走过的路径记录下来。现在,请你把他统计一下,所有路径中,回文串的数量(从前往后读和从后往前读一模一样的字符串称为回文串)。
输入输出格式
输入格式:
第一行包括一个整数N,表示农场的大小,接下来输入一个N*N的字母矩阵。
输出格式:
Please output the number of distinct palindromic routes Bessie can take,
modulo 1,000,000,007.
输出一个整数,表示回文串的数量。
输入输出样例
输入样例#1:
4 ABCD BXZX CDXB WCBA
输出样例#1:
12
题解:动态规划
设f[i][j][k]为起点开始竖方向向下走到i,横向走到j,从终点向上走到k,可知l=i+j-k
f[i][j][k]->f[i+1][j][k]&f[i][j+1][k]&f[i+1][j][k+1]&f[i][j+1][k+1](颜色相同)
最后答案就是i+j=n时的最大值
时空间复杂度都是O(n^3)但还有优化
可以把第一维换成步数,f[i][j][k]表示走i步,向下到i,向上到k
f[i][j][k]->f[i+1][j+1][k]&f[i+1][j+1][k+1]&f[i+1][j][k+1]&f[i+1][j][k]
用滚动数组消去一个n
此题巨坑,时间卡的紧,多谢YZD大佬指点才过
要点:若f[now][j][k]=0就不转移
还有一个超级玄学优化,将滚动数组的第一位放到第三维,每次开始前不清空f[][][nxt],改为在i<n时,转移后将
f[][][now]清空。比原来快1000ms
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 typedef long long lol; 7 int Mod=1000000007; 8 lol f[501][501][2]; 9 int now,nxt,n,m; 10 lol ans; 11 char a[501][501]; 12 void get(int i) 13 { 14 int x=0; 15 char ch=getchar(); 16 while (ch<'A'||ch>'Z') ch=getchar(); 17 while (ch>='A'&&ch<='Z') 18 { 19 x++; 20 a[i][x]=ch; 21 ch=getchar(); 22 } 23 } 24 int main() 25 { 26 register int i,j,k; 27 //freopen("b.in","r",stdin); 28 //freopen("b.out","w",stdout); 29 cin>>n; 30 m=n; 31 for (i=1; i<=n; i++) 32 { 33 get(i); 34 } 35 if (a[1][1]!=a[n][m]) 36 { 37 cout<<0<<endl; 38 return 0; 39 } 40 f[1][n][0]=1; 41 now=1; 42 nxt=0; 43 for (i=1; i<=n; i++) 44 { 45 swap(now,nxt); 46 for (j=1; j<=i; j++) 47 {int b=n-i+1; 48 for (k=n; k>=b; k--) 49 if(f[j][k][now]) 50 { 51 int y1=i-j+1,y2=m-i+n-k+1; 52 //printf("%d %d %d %d %d\n",i,j,y1,k,y2); 53 f[j][k][now]%=Mod; 54 if (j+1<=n&&k-1>=1&&a[j+1][y1]==a[k-1][y2]) 55 f[j+1][k-1][nxt]+=f[j][k][now]; 56 57 if (j+1<=n&&y2-1>=1&&a[j+1][y1]==a[k][y2-1]) 58 f[j+1][k][nxt]+=f[j][k][now]; 59 60 if (y1+1<=m&&k-1>=1&&a[j][y1+1]==a[k-1][y2]) 61 f[j][k-1][nxt]+=f[j][k][now]; 62 63 if (y1+1<=m&&y2-1>=1&&a[j][y1+1]==a[k][y2-1]) 64 f[j][k][nxt]+=f[j][k][now]; 65 if (i<n) 66 f[j][k][now]=0; 67 } 68 } 69 } 70 for (i=1; i<=n; i++) 71 ans=(ans+f[i][i][now])%Mod; 72 cout<<ans%Mod; 73 }