poj 2411 状态压缩DP 铺砖块

来源:互联网 发布:webassembly与java 编辑:程序博客网 时间:2024/05/22 01:48

判断1*2的砖块去填m*n的矩形总共的摆放方案

dp[i][j]表示当前行状态为j时的总共的摆放方案

 

先枚举上一层i的状态,如果存在某状态,就把还空的位置用竖的砖块插入,插满后,记录下当前i+1行的状态

然后在i+1行暴力枚举所有可能摆放方案,这个状态数再叠加上同一行上一个的状态(没有摆放横砖块之前)总数

最后的答案就是 dp[h][(1<<w)-1]即DP到最后一行,且摆满

#include<stdio.h>
#include<string.h>
int h,w;
__int64 dp[15][2050];
void dfs2(int row,int state,int col,int state2){
if(col>w) return ;
if(col==w) {
if(state2!=state)
dp[row][state2]+=dp[row][state];
return ;
}
if(!(state&(1<<col)) && !(state&(1<<(col+1))))
dfs2(row,state,col+2,state2+(1<<col) + (1<<(col+1)));
dfs2(row,state,col+1,state2);
}
void gao(){
int i,j;
dp[0][(1<<w)-1]=1;
for(i=0;i<h;i++){
for(j=0;j<(1<<w);j++)
if(dp[i][j]){
int s=0;
for(int x=0;x<w;x++)
if(!(j&(1<<x))) s+=(1<<x);
dp[i+1][s]+=dp[i][j];
}
for(j=(1<<w)-1;j>=0;j--)
if(dp[i+1][j])
dfs2(i+1,j,0,j);
}
}
int main(){
while(scanf("%d%d",&h,&w)!=EOF && h+w){
int temp;
if(h<w){
temp=h;h=w;w=temp;
}
memset(dp,0,sizeof(dp));
gao();
printf("%I64d\n",dp[h][(1<<w)-1]);
}
return 0;
}