poj2411
题意:n*m矩形,用1*2的方块填满有多少种方案数? (n,m<=11)
题解:考虑一行一行的填格子,0代表暂时不填,1代表填上。
那么对于某一行,考虑上一行能转移到它的状态,如果这一行的第j位是0,那么上一行第j位一定是1。
如果这一行的第j位是1,那么上一行第j位可以是1,也可以是0。
如果他的上一行第j位是0,那么没有限制,如果他的上一行第j位是1,说明这一行第j位的1一定由横着填来的,那么对上一行第j-1位添加限制,他只能是1.
#include<cstdio> #include<vector> using namespace std; const int N=1<<12; vector<int>G[N]; int n,m; long long f[N],tmp[N]; void dfs(int id,int p,bool lim,int sum){ if(p==m){ if(lim) return; G[id].push_back(sum); return ; } if(id&(1<<p)) { if(lim) dfs(id,p+1,0,sum+(1<<p)); else { dfs(id,p+1,0,sum); dfs(id,p+1,1,sum+(1<<p)); } } else { if(lim) return; dfs(id,p+1,0,sum+(1<<p)); } } int Ju(int x){ while(x){ if(x&1){ x>>=1; if(!(x&1)) return 0; x>>=1; } else x>>=1; } return 1; } int main(){ while(scanf("%d%d",&n,&m),n&&m){ for(int i=0;i<(1<<m);++i) G[i].clear(); for(int i=0;i<(1<<m);++i) { dfs(i,0,0,0); } for(int i=0;i<(1<<m);++i) { tmp[i]=Ju(i); } for(int i=2;i<=n;++i) { for(int j=0;j<(1<<m);++j) { for(int k=0;k<(int)G[j].size();++k) { f[j]+=tmp[G[j][k]]; } } for(int j=0;j<(1<<m);++j) { tmp[j]=f[j]; f[j]=0; } } printf("%lld\n",tmp[(1<<m)-1]); } }