寻宝之后

来源:互联网 发布:qq堂 mac 编辑:程序博客网 时间:2024/04/29 08:39

迷宫是一个n*m的字符矩阵。

小明在这个矩阵的左上角,只能向下和向右走,去和在矩阵右下角的小芳会合。

小明必须将他走过的路径上的,经过的字符收集起来。如果到右下角时他收集到的这些字符连在一起是回文的,那么他就能够走出这个迷宫,否则他就会掉进陷阱出不来。

小明想知道有多少条路径能够让他走出这个迷宫。由于答案可能很大,请对1000000007取模。


输入输出格式

输入格式:

第一行两个整数n和m。

接下来n行,每行m个字符表示这个矩阵,全部均为小写字母

输出格式:

输出一行一个整数表示答案

输入输出样例

输入样例#1:
3 4aaabbaaaabba
输出样例#1:
3

说明

n,m<=500

#include<iostream>#include<cstdio>#include<string>#include<cstring>using namespace std;const int dx[2][2]={{1,0},{-1,0}};const int dy[2][2]={{0,1},{0,-1}};const int MOD=1000000007;int n,m;int a[505][505],dp[2][505][505],ans=0;                 //dp[0,1][i][j]   表示第一个人走到第i行,第二个人走到第j行   int main(){int i,j,k,i1,i2,MAX_k;string ch;scanf("%d%d",&n,&m);for(i=1;i<=n;i++){cin>>ch;for(j=0;j<m;j++){a[i][j+1]=(int)(ch[j]-'a');}}if(a[1][1]==a[n][m]){dp[1][1][n]=1;}else{cout<<0<<endl;return 0;}MAX_k=(n+m)>>1;for(k=1;k<MAX_k;k++){                                           //枚举对角线 memset(dp[(k+1)&1],0,sizeof(dp[(k+1)&1]));                  //滚动数组初始化 int MAX_i1=min(k,n);for(i1=max(1,k-m+1);i1<=MAX_i1;i1++){int MIN_i2=max(i1,n+1-MAX_i1);for(i2=n+1-max(1,k-m+1);i2>=MIN_i2;i2--){int j1=k-i1+1,j2=n+m-k-i2+1;//cout<<k<<' '<<i1<<j1<<' '<<i2<<j2<<endl;for(i=0;i<2;i++){for(j=0;j<2;j++){int nx1=i1+dx[0][i],ny1=j1+dy[0][i];int nx2=i2+dx[1][j],ny2=j2+dy[1][j];//cout<<nx1<<' '<<ny1<<' '<<nx2<<' '<<ny2<<' '<<"gg"<<endl;if(nx1>n||ny1>m||nx2<1||ny2<1||nx1>nx2||ny1>ny2||a[nx1][ny1]!=a[nx2][ny2]) continue;dp[(k+1)&1][nx1][nx2]=(dp[(k+1)&1][nx1][nx2]+dp[k&1][i1][i2])%MOD;//cout<<nx1<<' '<<ny1<<' '<<nx2<<' '<<ny2<<' '<<i1<<i2<<' '<<dp[(k+1)&1][nx1][nx2]<<"gg"<<endl;}}}}}if((n+m)&1){for(i=1;i<=n;i++){ans=(ans+dp[MAX_k&1][i][i])%MOD;ans=(ans+dp[MAX_k&1][i][i+1])%MOD;}}else{for(i=1;i<=n;i++){ans=(ans+dp[MAX_k&1][i][i])%MOD;}}cout<<ans<<endl;return 0;}




原创粉丝点击