回文"/>
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 abbaOutput示例
3
题解:从起点和终点开始枚举走相同步数可以到达的点,由于知道sx,sy,ex,就可以得到ey=(m+n+2-sx-sy-ex),sx又能够通过滚动数组压缩空间,所以可以用dp[sx&1][sy][ex]来表示。
状态转移:dp[sx&1][sy][ex]=dp[(sx-1)&1][sy] [ex-1]+dp[sx&1][sy-1] [ex]+dp[(sx-1)&1][sy] [ex]+dp[sx&1][sy-1] [ex];
sx,sy<---sx-1,sy sx,sy<---sx,sy-1 sx,sy<---sx-1,sy sx,sy<---sx,sy-1
ex,ey<---ex-1,ey ex,ey<---ex-1,ey ex,ey<---ex,ey-1 ex,ey<---ex,ey-1
其中枚举sx,sy时注意该点应该位于矩形的上三角形部分(包括对角线),更新值时ex,ey应该满足sx<=ez&&sy<=ey(其他状态没有意义)
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=505;
const int mod=1e9+7;
int n,m;
char maze[maxn][maxn];
ll dp[2][maxn][maxn],ans;
int main(){scanf("%d%d",&n,&m);memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++) scanf("%s",maze[i]+1);if(maze[1][1]==maze[n][m]) dp[1][1][n]=1;for(int i=1;i<=n;i++){for(int j=1;2*(i+j)<=m+n+2;j++)for(int k=n;k>0;k--)if(i<=k&&j<=(n+m-i-j-k+2)&&maze[i][j]==maze[k][n+m+2-i-j-k]){dp[i&1][j][k]=(dp[i&1][j][k]+dp[i&1][j-1][k])%mod;dp[i&1][j][k]=(dp[i&1][j][k]+dp[i&1][j-1][k+1])%mod;dp[i&1][j][k]=(dp[i&1][j][k]+dp[(i-1)&1][j][k])%mod;dp[i&1][j][k]=(dp[i&1][j][k]+dp[(i-1)&1][j][k+1])%mod;if(k-i+(n+m-i-j-k+2)-j<=1) ans=(ans+dp[i&1][j][k])%mod;}for(int j=1;j<=m;j++)for(int k=1;k<=n;k++)dp[(i-1)&1][j][k]=0;}printf("%lld",ans);
}
更多推荐
1503 猪和回文
发布评论