題目:Mondriaan's Dreamide
連接:http://poj.org/problem?id=2411spa
題意:用 1*2 的瓷磚去填 n*m 的地板,問有多少種填法。3d
思路:code
好久好久之前便作過的一道題目,狀壓DP,當時寫得估計挺艱辛的,今天搜插頭DP又搜到它,就先用狀壓DP寫了下,順利多了,沒一會就出來了,惋惜由於long long沒有1A。blog
思路挺簡單,一行一行解決,每一列用1 表示對下一行有影響,用0 表示對下一行沒有影響,因此一行最多2048 種可能,而後要篩選一下,由於有些自己就不合理,有些由於上一行的影響變得不合理,而後簡單的三重循環搞定,發現之前的代碼效率更高,懶得追究了,一塊兒貼出來。get
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define N 200 5 typedef long long LL; 6 int ans[N],ao; 7 bool check(int i,int m) 8 { 9 int co=0,o=0; 10 while(i) 11 { 12 o++; 13 if(i&1) 14 { 15 if(co&1) return false; 16 else co=0; 17 } 18 else 19 { 20 co++; 21 } 22 i>>=1; 23 } 24 if((m-o)&1) 25 return false; 26 return true; 27 } 28 void find(int m) 29 { 30 for(int i=0;i<(1<<m);i++) 31 { 32 if(check(i,m)==1) 33 { 34 ans[ao++]=i; 35 } 36 } 37 } 38 void dis(int i,int m) 39 { 40 int o=0; 41 while(i) 42 { 43 printf("%d",i&1); 44 o++; 45 i>>=1; 46 } 47 for(int j=o;j<m;j++) 48 printf("0"); 49 printf("\n"); 50 } 51 int pre[12][410000],po; 52 LL dp[12][2050]; 53 bool check_2(int a,int b) 54 { 55 while(a) 56 { 57 if(a&1) 58 { 59 if(b&1); 60 else return false; 61 } 62 a>>=1; 63 b>>=1; 64 } 65 return true; 66 } 67 int main() 68 { 69 int n,m; 70 while(scanf("%d%d",&n,&m)!=EOF) 71 { 72 if(n==0&&m==0) break; 73 ao=0; 74 find(m); 75 memset(dp,0,sizeof(dp)); 76 po=0; 77 for(int i=0;i<ao;i++) 78 { 79 pre[0][po++]=ans[i]; 80 dp[0][ans[i]]=1; 81 } 82 int ko=0; 83 bool v[2050]={0}; 84 for(int i=1;i<n;i++) 85 { 86 memset(v,0,sizeof(v)); 87 for(int k=0;k<po;k++) 88 { 89 if(v[pre[i-1][k]]) continue; 90 v[pre[i-1][k]]=1; 91 for(int j=0;j<ao;j++) 92 { 93 if(check_2(pre[i-1][k],ans[j])) 94 { 95 //printf("pre %d ans %d\n",pre[i-1][k],ans[j]); 96 pre[i][ko++]=ans[j]^pre[i-1][k]; 97 dp[i][pre[i][ko-1]]+=dp[i-1][pre[i-1][k]]; 98 } 99 } 100 } 101 po=ko; 102 } 103 printf("%I64d\n",dp[n-1][0]); 104 } 105 return 0; 106 }
1 #include<stdio.h> 2 #include<string.h> 3 #define LL long long 4 LL dp[11][2048]; 5 6 // 1:影響到下一行 0:不影響下一行 7 8 bool check(int m, int up, int x){ 9 int flag=0; 10 while(m--){ 11 if(x&1){ 12 if(flag==1) return false; 13 if(up&1) return false; 14 } 15 else{ 16 if(up&1){ 17 if(flag==1) return false; 18 } 19 else flag^=1; 20 } 21 x>>=1; 22 up>>=1; 23 } 24 if(flag==1) return false; 25 return true; 26 } 27 28 int main(){ 29 int n, m; 30 while(scanf("%d%d", &n, &m)!=EOF){ 31 if(n==0 && m==0) break; 32 if(n*m%2==1){ 33 printf("0\n"); 34 continue; 35 } 36 memset(dp, 0, sizeof(dp)); 37 int c = (1 << m); 38 for(int i=0; i<c; i++){ 39 if(check(m, 0, i)){ 40 dp[0][i]=1; 41 } 42 } 43 for(int i=1; i<n; i++){ 44 for(int j=0; j<c; j++){ 45 if(dp[i-1][j]>0){ 46 for(int k=0; k<c; k++){ 47 if(check(m, j, k)){ 48 dp[i][k]+=dp[i-1][j]; 49 } 50 } 51 } 52 } 53 } 54 printf("%I64d\n", dp[n-1][0]); 55 } 56 return 0; 57 }