1. 程式人生 > >2331: [SCOI2011]地板 插頭DP

2331: [SCOI2011]地板 插頭DP

延伸 mage %d ever gcc to do BE 什麽 i++

國際慣例的題面:
技術分享圖片
十分顯然的插頭DP。由於R*C<=100,所以min(R,C)<=10,然後就可以愉悅地狀壓啦。
我們用三進制狀壓,0表示沒有插頭,1表示有一個必須延伸至少一格且拐彎的插頭,2表示有一個必須延伸一格且不可以拐彎的插頭。
轉移的話就十分顯然了。
00->22,表示用這個格子作為開始的拐角。
00->10,表示用這個格子向下延伸。
00->01,表示用這個格子向右延伸。
01->10,表示這個格子連接上下。
01->02,表示在這個格子作為中間的拐角。
02->20,表示這個格子連接上下。
02->00,表示這個格子作為某個地板的終點。
10->01,表示這個格子連接左右。
10->20,表示在這個格子作為中間的拐角。
11->00,表示這個格子作為結束的拐角。
20->00,表示這個格子作為某個地板的終點。
20->02,表示這個格子連接左右。
(插頭DP的本質就是分類討論,所以麻煩也沒辦法,想明白就很容易了)
然後就是實現了。我是用unordered_map存儲狀態,同時先找到第一個可以放東西的位置開始DP,統計答案的時候統計第n+1行沒有插頭的狀態。

代碼:

技術分享圖片
 1 #pragma GCC optimize(2)
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<tr1/unordered_map>
 5 using namespace std;
 6 using namespace tr1;
 7 const int maxn=1e2+1e2;
 8 const int mod=20110520;
 9 
10 int sta[maxn],nxt[maxn];
11 char in[maxn][maxn]; // in == 1 means empty .
12 int
n,m,cur,fx,fy; 13 unordered_map<int,int> f[2]; 14 15 inline void unzip(int* sta,int ss) { 16 for(int i=m+1;i;i--) sta[i] = ss % 3 , ss /= 3; 17 } 18 inline int zip(int* sta) { 19 int ret = 0; 20 for(int i=1;i<=m+1;i++) ret = ret * 3 + sta[i]; 21 return ret; 22 } 23 24 inline void
core_trans(unordered_map<int,int> &dst,int x,int y,int add) { 25 memcpy(nxt,sta,sizeof(int)*(m+2)); 26 if( !in[x][y] ) { // not empty . 27 if( sta[y] == 0 && sta[y+1] == 0 ) ( dst[zip(nxt)] += add ) %= mod; 28 return; 29 } 30 if( sta[y] == 0 ) { 31 if( sta[y+1] == 0 ) { 32 nxt[y] = 2 , nxt[y+1] = 2 , ( dst[zip(nxt)] += add ) %= mod; 33 nxt[y] = 1 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod; 34 nxt[y] = 0 , nxt[y+1] = 1 , ( dst[zip(nxt)] += add ) %= mod; 35 } else if( sta[y+1] == 1 ) { 36 nxt[y] = 1 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod; 37 nxt[y] = 0 , nxt[y+1] = 2 , ( dst[zip(nxt)] += add ) %= mod; 38 } else if( sta[y+1] == 2 ) { 39 nxt[y] = 2 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod; 40 nxt[y] = 0 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod; 41 } 42 } else if( sta[y] == 1 ) { 43 if( sta[y+1] == 0 ) { 44 nxt[y] = 0 , nxt[y+1] = 1 , ( dst[zip(nxt)] += add ) %= mod; 45 nxt[y] = 2 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod; 46 } else if( sta[y+1] == 1 ) nxt[y] = 0 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod; 47 } else if( sta[y] == 2 ) { 48 if( sta[y+1] == 0 ) { 49 nxt[y] = 0 , nxt[y+1] = 0 , ( dst[zip(nxt)] += add ) %= mod; 50 nxt[y] = 0 , nxt[y+1] = 2 , ( dst[zip(nxt)] += add ) %= mod; 51 } 52 } 53 } 54 inline void trans(const unordered_map<int,int> &sou,unordered_map<int,int> &dst,int x,int y) { 55 dst.clear(); 56 for(unordered_map<int,int>::const_iterator it=sou.begin();it!=sou.end();it++) if( it->second ) { 57 unzip(sta,it->first) , core_trans(dst,x,y,it->second); 58 } 59 } 60 inline void transline(const unordered_map<int,int> &sou,unordered_map<int,int> &dst) { 61 dst.clear(); 62 for(unordered_map<int,int>::const_iterator it=sou.begin();it!=sou.end();it++) if( it->second && ! ( it->first % 3 ) ) { 63 dst[it->first/3] = it->second; 64 } 65 } 66 67 inline void revert() { // make m <= n . 68 static char tp[maxn][maxn]; 69 memcpy(tp,in,sizeof(in)) , memset(in,0,sizeof(in)); 70 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) in[j][i] = tp[i][j]; 71 swap(n,m); 72 } 73 74 int main() { 75 scanf("%d%d",&n,&m) , fx = -1 , fy = -1; 76 for(int i=1;i<=n;i++) { 77 scanf("%s",in[i]+1); 78 for(int j=1;j<=m;j++) in[i][j] = in[i][j] == _; 79 } 80 81 if( n < m ) revert(); 82 for(int i=1;i<=n&&!~fx;i++) for(int j=1;j<=m&&!~fx;j++) if(in[i][j]) fx = i , fy = j; 83 if( !~fx ) return puts("1") , 0; // nothing to do . 84 sta[fy] = 0 , sta[fy+1] = 1 , f[cur][zip(sta)] = 1; 85 sta[fy] = 1 , sta[fy+1] = 0 , f[cur][zip(sta)] = 1; 86 sta[fy] = sta[fy+1] = 2 , f[cur][zip(sta)] = 1; 87 for(int j=fy+1;j<=m;j++) trans(f[cur],f[cur^1],fx,j) , cur ^= 1; 88 transline(f[cur],f[cur^1]) , cur ^= 1; 89 90 for(int i=fx+1;i<=n;i++) { 91 for(int j=1;j<=m;j++) 92 trans(f[cur],f[cur^1],i,j) , cur ^= 1; 93 transline(f[cur],f[cur^1]) , cur ^= 1; 94 } 95 96 printf("%d\n",f[cur][0]); 97 98 return 0; 99 }
View Code



たいせつなきみのために ぼくにできるいちばんのことは
為了最重要的你 我所能做的最好的事
約束を忘れること君への想い消し去ること
就是忘卻與你的約定抹去對你的思念
沈む夕日暮れてく空 夜の帳舞い降りる頃
漸漸歸隱大地的夕陽 夜幕降臨整個天空 夜的氣息輕盈飄落之時
僕は目を閉じて それは闇に溶けるように 滲んで消えた
我閉目去感受 一切就像溶入暗影一樣 滲透進去消散無痕了

未來なんていらないよ
未來(明日)什麽的已經不需要了吧
君が側にいる過去のままで
因為有你一直陪伴我的往昔(昨日)

2331: [SCOI2011]地板 插頭DP