Description
举行计算机科学家盛宴的大厅的地板为M×N (1<=M<=9, 1<=N<=9)的矩形。现在必须要铺上硬木地板砖。可以使用的地板砖形状有两种:
1) 2×1的矩形砖
2) 2×2中去掉一个1×1的角形砖你需要计算用这些砖铺满地板共有多少种不同的方案。
注意:必须盖满,地板砖数量足够多,不能存在同时被多个板砖覆盖的部分。
Input
包含M和N。
Output
输出方案总数,如果不可能那么输出0 。
Sample Input
2 3
Sample Output
5
状压DP,搜索求现在状态能达到的所以状态
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define N (1<<11)+3 #define ll long long ll f[10][N]; struct node { int to,next; }e[1<<20]; int head[N],cnt; void add(int x,int y) { e[cnt].to=y; e[cnt].next=head[x]; head[x]=cnt++; } int n,m; void dfs(int s1,int s2,int b1,int b2,int step) { if(step==m) { if(!b1&&!b2) { add(s1,s2); } return ; } dfs(s1|(b1<<step),s2|((1-b2)<<step),0,0,step+1); if(!b1 && !b2) { dfs(s1|(1<<step),s2,0,0,step+1); dfs(s1|(1<<step),s2,1,0,step+1); dfs(s1|(1<<step),s2,0,1,step+1); } if(!b1) { dfs(s1|(1<<step),s2|((1-b2)<<step),1,0,step+1); dfs(s1|(1<<step),s2|((1-b2)<<step),1,1,step+1); } if(!b2) { dfs(s1|(b1<<step),s2,1,1,step+1); } } int main() { memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); dfs(0,0,0,0,0); f[0][(1<<m)-1]=1; for(int i=0;i<n;i++) { for(int S=0;S<(1<<m);S++) { if(f[i][S]) { for(int k=head[S];k!=-1;k=e[k].next) { f[i+1][e[k].to]+=f[i][S]; } } } } printf("%lld ",f[n][(1<<m)-1]); return 0; }