Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 10047 | Accepted: 5809 |
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
用0表示竖着放的木块的上半部分,单独的1表示竖着的木块的下半部分,两个连续的1表示横着放的木块.
最后一行铺满的状态就是全部为1
上下行的兼容性:
1:下面为0上面一定不能为0
2:下面为1.....如果上面为0,那么这是一个单独的1
如果上面为1,那么这应该是一个连续的1,检查下一位是否为1,及下一位的上面是否为1
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<vector> using namespace std; const int N=22; long long dp[15][1<<14]; int n,m; bool ok(int s) { int cnt=0; for(int i=0;i<m;i++) if((s>>i)&1)cnt++; //if(cnt%2==1)return 0; for(int i=0;i<m;i++) { if((s>>i)&1) { if((s>>(i+1))&1) i++; else return 0; } } return 1; } void get() { for(int i=0;i<(1<<m);i++) { if(ok(i)) { dp[1][i]=1; /**for(int j=0;j<m;j++) cout<<((i>>j)&1)<<' '; cout<<endl;*/ } } } bool good(int down,int up) { for(int i=0;i<m;i++) { if(((down>>i)&1)==0) { if(((up>>i)&1)==0) return 0; } else{ if(((up>>i)&1)==0)continue; else { if(i+1>=m)return 0; if(((down>>(i+1))&1)==1) { if(((up>>(i+1))&1)==1) i++; else return 0; } else return 0; } } } return 1; } void solve() { int i,j,k;if(n<m)swap(n,m); memset(dp,0,sizeof dp); get(); for(i=2;i<=n;i++) { for(j=0;j<(1<<m);j++) { for(k=0;k<(1<<m);k++) if(good(j,k)) dp[i][j]+=dp[i-1][k]; } } cout<<dp[n][(1<<m)-1]<<endl; } int main() { while(scanf("%d%d",&n,&m)!=EOF&&n)//cin>>n>>m) solve(); }