Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 10402 | Accepted: 6035 |
Description
Input
Output
Sample Input
1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
Sample Output
1 0 1 2 3 5 144 51205
Source
[Submit] [Go Back] [Status] [Discuss]
给一个长,一个宽,求用1*2的地砖能恰好完全覆盖的方法有多少种。
研究了好久,终于有点理解了,采用状态压缩dp来枚举每一层的状态,然后层层递推,最后就可以得到了答案。
dfs状态压缩代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> using namespace std; long long dp[12][(1<<11)+1]; int m,n,k; void dfs(int c,int s1,int s2) { if(c==n) { dp[k][s1] += dp[k-1][s2]; return; } if(c+1<=n) { dfs(c+1,s1<<1,s2<<1|1); dfs(c+1,s1<<1|1,s2<<1); } if(c+2<=n) dfs(c+2,s1<<2|3,s2<<2|3); } int main() { while(~scanf("%d%d", &m ,&n) && m) { if(n>m) swap(n,m); memset(dp,0,sizeof(dp)); dp[0][(1<<n)-1]=1; for(k=1; k<=m; k++) dfs(0,0,0); printf("%lld\n",dp[m][(1<<n)-1]); } return 0; }
代码:
#include<iostream> #include<cstring> using namespace std; long long f[2][1<<12],i,j,ps,p=0,c=1,n,m; int main() { while (scanf("%d%d",&n,&m),n!=0) { memset(f[c],0,sizeof(f[c])); f[c][(1<<m)-1]=1; for (i=0;i<n;i++) for (j=0;j<m;j++) { swap(p,c);memset(f[c],0,sizeof(f[c])); for (ps=0;ps<1<<m;ps++) if (f[p][ps]) { if (j>0&&(!(ps&(1<<j-1)))&&(ps&(1<<j))) f[c][ps|1<<(j-1)]+=f[p][ps]; if (!(ps&1<<j)) f[c][ps|1<<j]+=f[p][ps]; if (ps&1<<j) f[c][ps^1<<j]+=f[p][ps]; } } printf("%lld\n",f[c][(1<<m)-1]); } }
原文:http://blog.csdn.net/xianxingwuguan1/article/details/19039259