51 Nod 1503 猪和回文
一只猪走进了一个森林。很凑巧的是,这个森林的形状是长方形的,有n行,m列组成。我们把这个长方形的行从上到下标记为1到n,列从左到右标记为1到m。处于第r行第c列的格子用(r,c)表示。
刚开始的时候猪站在(1,1),他的目标是走到(n,m)。由于猪回家心切,他在(r,c)的时候,只会往(r+1,c)或(r,c+1)走。他不能走出这个森林。
这只猪所在的森林是一个非同寻常的森林。有一些格子看起来非常相似,而有一些相差非常巨大。猪在行走的过程中喜欢拍下他经过的每一个格子的照片。一条路径被认为是漂亮的当且仅当拍下来的照片序列顺着看和反着看是一样的。也就是说,猪经过的路径要构成一个回文。
数一数从(1,1)到(n,m)有多少条漂亮路径。答案可能非常巨大,请输出对 109+7 取余后的结果。
样例解释:有三种可能
Input
单组测试数据。
第一行有两个整数 n,m (1≤n,m≤500),表示森林的长和宽。
接下来有n行,每行有m个小写字母,表示每一个格子的类型。同一种类型用同一个字母表示,不同的类型用不同的字母表示。
Output
输出答案占一行。
Input示例
3 4
aaab
baaa
abba
Output示例
3
思路:动态规划 虽然我没有看出来
挺有意思的一道题
dp[i][j][k][z] 表示从(1,1)到(i,j) 和从(n,m) 到(k,z) 一共有多少方案
求回文路径数 一次必须选两个点 两个点的字符是相同的
我们 知道 x1,y1,x1 可以推出 y2 (我不知道怎么推 但是其他题解都说能推)
就可以去掉最后一维
每次 i 只和 i-1 有关 可以用滚动数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cctype> 2 #include <cstdio> 3 #include <cstring> 4 5 const int mod=1e9+7; 6 7 const int MAXN=510; 8 9 int n,m,ans; 10 11 int dp[2][MAXN][MAXN]; 12 13 char s[MAXN][MAXN]; 14 15 int hh() { 16 scanf("%d%d",&n,&m); 17 for(int i=1; i<=n; ++i) 18 scanf("%s",s[i]+1); 19 20 dp[1][1][n]=(s[1][1]==s[n][m]); 21 22 for(int i=1; i<=n; ++i) { 23 for(int j=1; j<=m; ++j) 24 for(int k=n; k>=1; --k) { 25 if(i+j-1>n+m-i-j+1) continue; 26 int z=n+m+2-i-j-k; 27 if(s[i][j] == s[k][z]) { 28 dp[i&1][j][k] = (dp[i&1][j][k] + dp[(i-1)&1][j][k+1])%mod; 29 dp[i&1][j][k] = (dp[i&1][j][k] + dp[(i-1)&1][j][k])%mod; 30 dp[i&1][j][k] = (dp[i&1][j][k] + dp[i&1][j-1][k+1])%mod; 31 dp[i&1][j][k] = (dp[i&1][j][k] + dp[i&1][j-1][k])%mod; 32 if( (i==k&&j==z) || (i+1==k&&j==z) || (i==k&&j+1==z) ) ans=(ans+dp[i&1][j][k])%mod; 33 } 34 } 35 memset(dp[(i-1)&1],0,sizeof dp[(i-1)&1]); 36 } 37 38 printf("%d\n",ans); 39 40 return 0; 41 } 42 43 int sb=hh(); 44 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现