http://poj.org/problem?id=2411
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题目大意:用1*2的砖,铺满n*m的表格,问有多少方案
/** 状态压缩dp 思路都是用0和1表示,用11表示横放 上一行0 下一行1表示竖放, 因为这一行的状态只和上一行有关。这样表示最后一行一定都是1,结果就是dp[n][(1<<m)-1], 用dfs搜一遍所有情况,s1是上一行 s2表示下一行 用vector存一下。 特判一下第一行,因为是第一行所以可以有任意个0,但相邻1的个数一定是偶数。 所有准备工作都完成之后进行状态转移 */ #include <iostream> #include <vector> #include <cstring> #include <cstdio> using namespace std; const int N=1<<11; long long int dp[2][N]; vector<int> vec[N]; void dfs(int cnt,int s1,int s2,int n) { if(n==cnt) { vec[s2].push_back(s1); return; } dfs(cnt+1,s1<<1,s2<<1|1,n); dfs(cnt+1,s1<<1|1,s2<<1,n); if(cnt<n-1) dfs(cnt+2,s1<<2|3,s2<<2|3,n); } int pdf(int a) { while(a>0) { if((a&3)==3)a>>=2; else if(a%2==0)a>>=1; else return 0; } return 1; } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { if(n==0) break; memset(dp[0],0,sizeof(dp[0])); memset(vec,0,sizeof(vec)); dfs(0,0,0,m); for(int i=0; i<1<<m; i++) if(pdf(i))dp[0][i]=1; int cnt=0; for(int i=1; i<n; i++) { cnt^=1; memset(dp[cnt],0,sizeof(dp[cnt])); for(int j=0; j<1<<m; j++) for(int k=0; k<vec[j].size(); k++) dp[cnt][j]+=dp[cnt^1][vec[j][k]]; } printf("%lld\n",dp[cnt][(1<<m)-1]); } return 0; }