poj2411 状态压缩-铺地板题型-轮廓线解法(最优)
解法参考博客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 状态压缩-铺地板题型-轮廓线解法(最优)的更多相关文章
- POJ2411 状态压缩dp
POJ2411 http://poj.org/problem?id=2411
- [ACM_动态规划] 轮廓线动态规划——铺放骨牌(状态压缩1)
Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, af ...
- 状态压缩dp(hdu2167,poj2411)
hdu2167 http://acm.hdu.edu.cn/showproblem.php?pid=2167 给定一个N*N的板子,里面有N*N个数字,选中一些数字,使得和最大 要求任意两个选中的数字 ...
- HihoCoder第九周 状态压缩 二 与POJ2411总结
在此我向各位博友求助,特别想知道除了HihoCoder上面的结果要对1e9+7取余之外,这两道题还有什么其他的问题,都是骨牌覆盖问题,都是状态压缩+dp,为什么我能过poj2411的程序过不了Hiho ...
- 转 状态压缩DP
引入 首先来说说“状态压缩动态规划”这个名称,顾名思义,状态压缩动态规划这个算法包括两个特点,第一是“状态压缩”,第二是“动态规划”. 状态压缩: 从状态压缩的特点来看,这个算法适用的题目符合以下的条 ...
- 状态压缩dp小结
最近一段时间算是学了一些状态压缩的题目,在这里做个小结吧 首先是炮兵布阵类题目,这类题目一开始给定一个矩形,要求在上面放置炮兵,如果在一格放了炮兵那么周围的某些格子就不能放炮兵,求最大能放置炮兵的数量 ...
- DP大作战—状态压缩dp
题目描述 阿姆斯特朗回旋加速式阿姆斯特朗炮是一种非常厉害的武器,这种武器可以毁灭自身同行同列两个单位范围内的所有其他单位(其实就是十字型),听起来比红警里面的法国巨炮可是厉害多了.现在,零崎要在地图上 ...
- hdu1565 网络流或状态压缩DP
对于网络流有一个定理: 最小点权覆盖集=最大网络流: 最大点权独立集=总权值-最小点权覆盖集: 网络流解法代码如下: #include<cstdio> #include<iostre ...
- SGU131 - Hardwood floor(状态压缩DP)
题目大意 给定一个N*M大小的矩形,要求你用1*2和2*2(缺个角)的砖块把矩形铺满(不能重叠),问总共有多少种铺法? 题解 受POJ2411的影响,怎么都没想到3,4,5,6这几种情况该怎么放置,看 ...
随机推荐
- 虚拟节点操作——DocumentFragment
文章中转站: DocumentFragment对象 createDocumentFragment()用法总结 深入理解DOM节点类型第四篇——文档片段节点DocumentFragment
- XML解析技术-dom4j
- 微信小程序-用户拒绝授权使用 wx.openSetting({}) 重新调起授权用户信息
场景模拟:用户进入微信小程序-程序调出授权 选择拒绝之后,需要用到用户授权才能正常使用的页面,就无法正常使用了. 解决方法:在用户选择拒绝之后,弹窗提示用户 拒绝授权之后无法使用,让用户重新授权(微信 ...
- setInterval 传值设参数
<script type="text/javascript" > window.onload=function(){ for(var i=1;i<3;i++){ ...
- 使用Numpy将数据集中的data和target同时shuffle
假设现在有图像数据imgs和对应标签targets.数据维度分别如下 imgs.shape = (num, channel, width, height) targets.shape = (num, ...
- mysql for linux6.8单机版安装
主机名以及hostname文件修改 vi /etc/hosts vi /etc/sysconfig/network hostname mysql01 系统参数修改 设置用户资源限制 vi /etc/s ...
- 20165221 JAVA第五周学习心得
课本知识点 内部类与异常类 内部类:在一个类中定义另一个类 特点:外嵌类的成员在内部类仍然有效,内部类也可调用外嵌类的方法,内部类的类体不能声明类变量及类方法 非内部类不能是static类 匿名类:创 ...
- android动态设置组件LayoutParams
开发中经常用到动态设置组件的LayoutParams,之前开发遇到的问题如下: LinearLayout.LayoutParams params = new LinearLayout.LayoutPa ...
- iris数据集(鸢尾花)
包含三个花的品种(Iris setosa(山鸢尾),Iris virginica(北美鸢尾),Iris versicolor(变色鸢尾)) 每个品种各50个样 每个样本四个特征参数(萼片长度和宽度.花 ...
- Codeforces 408D Long Path (DP)
题目: One day, little Vasya found himself in a maze consisting of (n + 1) rooms, numbered from 1 to (n ...