状压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]);
    }
 }
时间: 2024-08-29 00:55:59

状压DP入门——铺砖块的相关文章

poj 3254 Corn Fields 状压dp入门

// poj3254 状压dp入门 // dp[i][S]表示前i行第i行状态为S时放牧的情况 // S为十进制的二进制数形式如5为101表示第一列和第三列放牧的方法数 // 首先dp[0][S]合法的话就是1 // 状态转移方程为dp[i][S] = sigma(dp[i-1][V])(S与V是合法状态) // 最后的结果就是dp[n][S](S为所有的合法状态) // // 刚开始十分傻x的dp[0][S]置为get(S),...get(S)是其中1的个数 // 这又不是求放羊的数量,这是方

poj 2411 Mondriaan&#39;s Dream 状压dp入门

题意: 求h*w的矩形被1*2的小矩形覆盖的方案数. 分析: 状压dp入门,<挑战程序设计竞赛>上讲的很好,好几天才看懂. 代码: #include <iostream> using namespace std; __int64 ans[16][16]; int n,m; __int64 dp[2][1<<16]; __int64 solve() { int i,j,used; memset(dp,0,sizeof(dp)); __int64 *crt=dp[0],*n

POJ3254 状压DP入门

题目:http://poj.org/problem?id=3254 因为&运算写成&&--导致调试了快一个小时代的代码没有搞定 关于建图: 1.题目中是1表示可以放牧,0表示不可以放牧,但是建图的时候,可以放牧的位用0表示,不可以放牧的位用1表示.原因如下: 假设可以放牧的位用1表示,不可以放牧的位用0表示,那么假设当前行状态时1010   想要放置1001 ,&运算的结果是1,但是显然不合法, 也就是说  设值状态的意义,以及怎么判断是不是合法,这个在做之前一定考虑清楚再

状压dp入门

(先处理好基本的位运算的东西) 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.'&'符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.'|'符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.'^'符号,x^y,会将两个十进制数在二进制下进行异或运算,然后返回其十进制下的值.例如3(11)^2(10)=1(01). 4.'<&

POJ 1185 炮兵阵地(状压DP入门)

http://poj.org/problem?id=1185 状压DP: 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int dp[105][100][100]; 7 int ma[105],st[105]; 8 9 int ok(int x) 10 { 11 return (x&(x<<1))+(x&(x&

poj 2441 Arrange the Bulls(状压DP入门)

Arrange the Bulls Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 3509   Accepted: 1344 Description Farmer Johnson's Bulls love playing basketball very much. But none of them would like to play basketball with the other bulls because the

poj 2441 Arrange the Bulls 状压dp入门

题意: 将n头牛和m个栏做匹配,求匹配方案数. 分析: 开始暴搜tle了,还是要用状压dp,dp[i][s]表示前i头牛匹配栏的状态为s时可行的方案数. 代码: //poj 2441 //sep9 #include <iostream> using namespace std; const int maxN=21; int dp[2][1<<maxN]; int a[maxN][maxN]; int main() { int n,m; scanf("%d%d",

poj 3254 状压dp入门题

1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相邻,求有多少种放法. #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #d

状压dp入门第一题 poj3254

题目链接 http://poj.org/problem?id=3254 转自http://blog.csdn.net/harrypoirot/article/details/23163485 1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <iostream> 6 #include <sstream