1. 程式人生 > >codeforce 570 problem E&& 51Nod-1503-豬和回文

codeforce 570 problem E&& 51Nod-1503-豬和回文

-i 格子 med gif pac cst ons ray ring

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題 和之前1的傳紙條有點像 但這個是一個從(1,1)出發 一個從(n,m)出發
f【i】【j】【k】表示一個點到(i,j)另一個到(k,l)

l可以從另外三個數推出來 因為兩個點所走的路程一定一樣
技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=1e9+7;
const int M=507;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=
0&&c<=9){ans=ans*10+(c-0); c=getchar();} return ans*f; } char s[M][M]; int f[2][M][M],now=1,last=0; int h,n,m,ans; int main() { n=read(); m=read(); h=(n+m)>>1; for(int i=1;i<=n;i++) scanf("%s",s[i]+1); if(s[1][1]!=s[n][m]){printf("0\n"); return 0;} f[1][1][n]=1; for(int i=1;i<=n;i++){ for(int j=1;j<=(h-i+1);j++){ for(int k=n;k>=max(1,n-i-j+2);k--){ int l=n+m-i-j-k+2; if(s[i][j]!=s[k][l]) continue; (f[now][j][k]+=f[last][j][k])%=mod; (f[now][j][k]+=f[last][j][k+1])%=mod; (f[now][j][k]+=f[now][j-1][k+1])%=mod; (f[now][j][k]+=f[now][j-1][k])%=mod; if((i==k&&j==l)||(i==k&&j+1==l)||(i+1==k&&j==l)) (ans+=f[now][j][k])%=mod; } } memset(f[last],0,sizeof(f[last])); swap(last,now); }printf("%d\n",ans); return 0; }
View Code

 

codeforce 570 problem E&& 51Nod-1503-豬和回文