51nod 1503 多線程dp
阿新 • • 發佈:2017-08-20
gray long view sin tool sca row 51nod char
Input示例
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1503
1503 豬和回文
題目來源: CodeForces 基準時間限制:2 秒 空間限制:131072 KB 分值: 40 難度:4級算法題 收藏 關註一只豬走進了一個森林。很湊巧的是,這個森林的形狀是長方形的,有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
輸出答案占一行。
3 4 aaab baaa abbaOutput示例
一開始算錯空間大小,用的記憶化搜索結果T了三個大數據,後來發現這個題目類似於之前寫過的雙線dp,‘傳紙條’,,,,,,
dp[x1][y1][x2][y2] 表示從(1,1)出發走到(x1,y1),和從(n,m)出發到了(x2,y2)之後可能的方案數,註意走的必須是相同步數,因為是回文串,所以走到某一步時兩個字符必須相同才能
轉移狀態,否則表示不能直接continue,轉移時找到每個點對應的上一步就好了。
由於坐標和步數有關我們可以只記錄橫坐標和步數來降維,由於回文,只判斷到兩者相遇或者相鄰即可,步數也只要循環到一半,最後的步數裏的狀態加一起就是答案,51nod有點卡常,之前寫的%
太多還是T,最後改成一個才A掉,cf上就飛快啦。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 LL mod=1e9+7; 5 int f[2][505][505],N,M; 6 char e[505][505]; 7 int main() 8 { 9 int i,j,k,cur=0,ans=0; 10 scanf("%d%d",&N,&M); 11 for(i=1;i<=N;++i) scanf("%s",e[i]+1); 12 f[cur][1][N]=e[1][1]==e[N][M]?1:0; 13 for(int bs=1;bs<=(N+M-2)/2;++bs) 14 { 15 cur^=1; 16 memset(f[cur],0,sizeof(f[cur])); 17 for(int x1=1;x1<=N;++x1) 18 { 19 for(int x2=x1;x2<=N;++x2) 20 { 21 LL s=0; 22 int y1=bs-x1+2; 23 int y2=M-(bs-(N-x2)); 24 if(y1<0||y2<0||y1>M||y2>M||e[x1][y1]!=e[x2][y2]||(!(x2>=x1&&y2>=y1))) continue; 25 s=(s+f[cur^1][x1][x2]+f[cur^1][x1][x2+1]+f[cur^1][x1-1][x2]+f[cur^1][x1-1][x2+1])%mod; 26 f[cur][x1][x2]=(f[cur][x1][x2]+s)%mod; 27 } 28 } 29 } 30 for(int x1=1;x1<=N;++x1) 31 for(int x2=x1;x2<=N;++x2) ans=(ans+f[cur][x1][x2])%mod;; 32 printf("%d\n",ans); 33 return 0; 34 }
51nod 1503 多線程dp