1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
1 0 1 2 3 5 144 51205
将1*2的方块放入n*m的格子,问有几种放法。
状态压缩,将一行压缩到一起,0表示此位置没有方块,1表示此位置已经被占用。
首先预处理一下,求出第一行可能的状态。第x位横放则为11不放则为0。
然后dfs进行搜索,第i-1行的第x位为0,则第i行的x位必为竖放1,若i-1行的x位为1,则第i行的x位有不放0,横放11两种可能。
#include <iostream> #include <cstring> using namespace std; const long long maxn=(1<<11); long long n,m,i; long long f[14][maxn]; void init(long long x,long long now) { if (x==m+1) f[1][now]++; if (x>m) return; init(x+1,now<<1); init(x+2,(now<<2)|3); } void dfs(long long x,long long lst,long long nxt) { if (x==m+1){ f[i][nxt]+=f[i-1][lst]; //cerr<<x<<" "<<lst<<" "<<nxt<<endl; //cerr<<f[i][nxt]<<" "<<f[i-1][lst]<<endl; } //cerr<<i<<" "<<nxt<<" "<<f[i][nxt]<<endl; if (x>m) return; dfs(x+1,(lst<<1)|1,nxt<<1); dfs(x+1,lst<<1,(nxt<<1)|1); dfs(x+2,(lst<<2)|3,(nxt<<2)|3); } int main() { while (cin>>n>>m) { if (m==0&&n==0) break; if (m>n) swap(m,n); memset(f,0,sizeof(f)); init(1,0); //for (int j=0;j<=(1<<m)-1;j++){//if (f[1][j]>0) cerr<<j<<endl;//cerr<<f[1][j]<<endl;} for (i=2;i<=n;i++) { dfs(1,0,0); //for (int j=0;j<=(1<<m)-1;j++){cerr<<f[i][j]<<" ";/*if (f[i][j]>0) cerr<<j<<" ";*/}cerr<<endl; } cout<<f[n][(1<<m)-1]<<endl; } return 0; }