解法参考博客https://blog.csdn.net/u013480600/article/details/19569291

一种做法是先打出所有的状态,即满足上下配对的所有可能方案,然后再逐行进行枚举计数

dp[i][s]=sum{dp[i-1][t]},t是所有和s配对的状态

打状态时要注意如果i-1的j是0,那么i的j必定是1,i剩下的位置要必须一对对填入1,也可以用0填入,即枚举i行的横放砖块的起始位置k即可,如果i-1的k或k+1有一个不是1,那么显然不能放下

/*
对于每一行,用11表示一个横放的方块,用0表示竖放方块的第一格,1表示竖放方块的第二格
枚举i-1行的状态,推出i行的状态
如果i-1行的j位置是0,那么第i行的j必须是1,第i行剩下的地方要么填连续两个1要么填0
第n行的状态必须都是1
*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define ll long long
ll dp[][<<];
int n,m,w,path[][];//所有可能的配对方案
void get(int m){
for(int i=;i<=(<<m)-;i++)
for(int j=;j<=(<<m)-;j++){
int ok=;
for(int k=;k<m;k++)
if(ok){
if( !(i&(<<k)) ){//i的第k位是0
if(!(j&(<<k))){
ok=;break;
}
}
else{//i的第k位是1,其实是在枚举j状态横放的起点位置
if(!(j&(<<k)))continue;//j的第k位是0
++k;
if(k>=m || !(i&(<<k))){//i没有第k+1位或者i的第k+1位是0,所以j在k位置不可能横放了
ok=;break;
}
else if( (j&(<<(k-))) && !(j&(<<k)) ){//j的状态是10,显然不可能
ok=;break;
}
}
}
if(ok)path[w][]=i,path[w++][]=j;
}
}
int main(){
while(cin>>n>>m,n){
w=;
if(m>n)swap(n,m);
get(m);
memset(dp,,sizeof dp);
dp[][(<<m)-]=;
for(int i=;i<n;i++)
for(int j=;j<w;j++)
dp[i+][path[j][]]+=dp[i][path[j][]];
printf("%lld\n",dp[n][(<<m)-]);
}
}

另外一种解法

/*
用0和1表示某个位置放不放砖块,如果是0则表示让下一行来补,如果是1则有两种可能,一种是横放,一种是填补上一行的0
对应这三种情况,可以搜索出所有可能的配对情况
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[][<<];
int path[][],n,m,w;
void get(int c,int pre,int now){
if(c>m)return;
else if(c==m){
path[w][]=pre;
path[w++][]=now;
return;
}
get(c+,(pre<<)|,now<<);//后一行不放,前一行必定是1
get(c+,pre<<,(now<<)|);//前一行0,后一行必定是1
get(c+,(pre<<)|,(now<<)|);//前一行横放,后一行也是横放
}
int main(){
while(cin>>n>>m,m){
w=;
if(m>n)swap(n,m);
get(,,);
memset(dp,,sizeof dp);
dp[][(<<m)-]=;//初始条件不可忽略!
for(int i=;i<n;i++)
for(int j=;j<w;j++)
dp[i+][path[j][]]+=dp[i][path[j][]];
printf("%lld\n",dp[n][(<<m)-]);
}
}

最后是轮廓线解法:遍历一次方格,每扫到一个方格时枚举所有可能的轮廓线,然后由上一个格子(上一个状态的轮廓线)推出当前状态的轮廓线所对应的摆放方案数,以此推到最后一个格子

使用滚动dp数组,覆盖之前无效的信息即可

/*
轮廓线解法
*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define ll long long
ll dp[][<<];
int n,m,cur;
void update(int a,int b){//a是包含m位的旧状态,b是包含m+1位的新状态
if(b&(<<m))//如果b的首位是1才进行转移,即如果b的首位是0的话是不成立的
dp[cur][b^(<<m)]+=dp[cur^][a];
}
int main(){
while(cin>>n>>m,m){
if(m>n)swap(m,n);
memset(dp,,sizeof dp);
cur=;
dp[][(<<m)-]=;//边际条件算第一种方案:需要由这个初始状态推导出其他状态
for(int i=;i<n;i++)
for(int j=;j<m;j++){
cur^=;
memset(dp[cur],,sizeof dp[cur]);//把上一轮的状态清零
for(int k=;k<(<<m);k++){//枚举当前所有可能的轮廓线状态
//三种可能
update(k,k<<);//[i,j]不放
if(i && !(k&(<<(m-))))update(k,(k<<)^(<<m)^);//向上摆放
if(j && !(k&))update(k,(k<<)^);//向左摆放
}
}
printf("%lld\n",dp[cur][(<<m)-]);
}
}

poj2411 状态压缩-铺地板题型-轮廓线解法(最优)的更多相关文章

  1. POJ2411 状态压缩dp

    POJ2411 http://poj.org/problem?id=2411

  2. [ACM_动态规划] 轮廓线动态规划——铺放骨牌(状态压缩1)

    Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, af ...

  3. 状态压缩dp(hdu2167,poj2411)

    hdu2167 http://acm.hdu.edu.cn/showproblem.php?pid=2167 给定一个N*N的板子,里面有N*N个数字,选中一些数字,使得和最大 要求任意两个选中的数字 ...

  4. HihoCoder第九周 状态压缩 二 与POJ2411总结

    在此我向各位博友求助,特别想知道除了HihoCoder上面的结果要对1e9+7取余之外,这两道题还有什么其他的问题,都是骨牌覆盖问题,都是状态压缩+dp,为什么我能过poj2411的程序过不了Hiho ...

  5. 转 状态压缩DP

    引入 首先来说说“状态压缩动态规划”这个名称,顾名思义,状态压缩动态规划这个算法包括两个特点,第一是“状态压缩”,第二是“动态规划”. 状态压缩: 从状态压缩的特点来看,这个算法适用的题目符合以下的条 ...

  6. 状态压缩dp小结

    最近一段时间算是学了一些状态压缩的题目,在这里做个小结吧 首先是炮兵布阵类题目,这类题目一开始给定一个矩形,要求在上面放置炮兵,如果在一格放了炮兵那么周围的某些格子就不能放炮兵,求最大能放置炮兵的数量 ...

  7. DP大作战—状态压缩dp

    题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...

  8. hdu1565 网络流或状态压缩DP

    对于网络流有一个定理: 最小点权覆盖集=最大网络流: 最大点权独立集=总权值-最小点权覆盖集: 网络流解法代码如下: #include<cstdio> #include<iostre ...

  9. SGU131 - Hardwood floor(状态压缩DP)

    题目大意 给定一个N*M大小的矩形,要求你用1*2和2*2(缺个角)的砖块把矩形铺满(不能重叠),问总共有多少种铺法? 题解 受POJ2411的影响,怎么都没想到3,4,5,6这几种情况该怎么放置,看 ...

随机推荐

  1. Springboot(一)概念

    一.概念 Spring boot 用来简化新Spring应用的初始搭建和开发配置. 二.特性 1.创建独立的Spring应用程序,不是对spring功能增强,而是提快速使用Spring的功能: 2.嵌 ...

  2. ASP.NET - ADO.NET框架

    ADO.NET(ActiveX Data Objects) ADO.NET是一个COM组件库,用于在使用Microsoft技术的代码中访问数据库. SQL数据操作类 SqlConnection类(Sy ...

  3. python练习 之 实践出真知 中心扩展法求最大回文子串 (leetcode题目)

    1 问题,给定一个字符串,求字符串中包含的最大回文子串,要求O复杂度小于n的平方. 首先需要解决奇数偶数的问题,办法是:插入’#‘,aba变成#a#b#a#,变成奇数个,aa变成#a#a#,变成奇数个 ...

  4. Django url管理之include

    在Django框架中,提供了非常清晰简洁的url管理方法,在新建一个project之后(此处为myproject),然后在项目中建立一个app(此处为myapp),会看到有如下的目录结构: 一般所熟知 ...

  5. tomcat目录映射

    环境:CentOS 6 + tomcat 7 + jdk 7 目前使用2种方法: 1.tomcat/conf/server.xml <Host name="localhost" ...

  6. 判断HDFS文件是否存在

    hadoop判断文件是否存在 在shell中判断一个HDFS目录/文件是否存在 直接看shell代码: hadoop fs -test -e /hdfs_dirif [ $? -ne 0 ]; the ...

  7. Libevent源码分析系列【转】

    转自:https://www.cnblogs.com/zxiner/p/6919021.html 1.使用libevent库     源码那么多,该怎么分析从哪分析呢?一个好的方法就是先用起来,会用了 ...

  8. http和ftp下载的区别

    HTTP和FTP是两种网络传输协议的缩写,FTP是File Transportation Protocol(文件传输协议)的缩写,而HTTP则是Hyper Text Transportation Pr ...

  9. 第八章 让Bootstrap轮播插件carousel支持左右滑动手势的三种方法

    因为最近开发的项目涉及到移动设备上的 HTML5 开发,其中需要实现轮播效果.然后最快捷的方式,你知道的(Bootstrap),然后原生的 Bootstrap 的 carousel.js 插件并没有支 ...

  10. mybatis:三种参数传递(转载)

    转载自:https://www.2cto.com/database/201409/338155.html 第一种方案 DAO层的函数方法 Public User selectUser(String n ...