状压DP入门——铺砖块
Posted dancer16
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压DP入门——铺砖块相关的知识,希望对你有一定的参考价值。
题目描述
现有n*m的一块地板,需要用1*2的砖块去铺满,中间不能留有空隙。问这样方案有多少种
输入
输入n,m(1<=n, m<=11)
有多组输入数据,以m=n=0结束
输出
输出铺砖块的方案数
样例输入
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
我A的第一道状压DP题是导游,感觉就是背包~~
此题不是很懂
此题状压DP,DP[i][sta]表示前i行填满对第i+1行的影响为状态sta时的方案总数
易知DP[0][0]=1;目标值f[i][0];
关于sta:sta表示当前此行对下一行的影响
定义竖铺时上一行为1,这一行为0;横铺时均为0;
可以推得状态若上一行为1,这一行必为0(竖铺一块嘛);
若上一行为0,可以竖铺一块填满下面的一块,这样下一行就为0;
若上一行为00,下一行为00;
关于DP的转移:dfs生成每个前一行和后一行的状态
#include<cstdio> #include<algorithm> #include<cstring> #define rep(i,a,b) for(int i=a;i<=b;++i) using namespace std; long long n,m,num,dp[150][40970],change[40970][20]; void dfs(int l,int pre,int now) { if(l>m) return; if(l==m) { change[++num][0]=pre; change[num][1]=now; } dfs(l+1,pre<<1,now<<1|1); dfs(l+2,pre<<2,now<<2); dfs(l+1,pre<<1|1,now<<1); } int main() { //f[i][sta]琛ㄧず鍓峣琛屽~婊″绗琲+1鐨勫奖鍝? while(~scanf("%d %d",&n,&m)&&n!=0&&m!=0) { if(n>m) swap(n,m); num=0; dfs(0,0,0); memset(dp,0,sizeof(dp)); dp[0][0]=1; rep(i,1,n) { rep(j,1,num) { dp[i][change[j][1]]+=dp[i-1][change[j][0]]; } } printf("%lld\n",dp[n][0]); } }
以上是关于状压DP入门——铺砖块的主要内容,如果未能解决你的问题,请参考以下文章
POJ2411 Mondriaan's Dream 题解 轮廓线DP