Description:

给你一个n * m的方格纸,有一些格子无法被覆盖,然后用2*3的格子覆盖这个方格纸,问你最多能放多少个格子

神级状压

为了弄清楚这道题翻了无数篇解题报告,最后终于搞明白了

用三进制表示每行的状态。

比如对于第i行第j列的格子,如果i-1行,i行的j列都是空的则用0表示,i行的j列不能放用2表示,剩下的(仅i - 1行的j列不能放)用1表示

然后深搜进行转移

干讲没意思,具体看注释,写的很清楚了(AC代码是poj的,稍微改一下输入输出就是洛谷的、

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = ;
/*pre表示你枚举的上一个状态,now表示你现在枚举的状态*/
int dp[][N], mp[][], pre[], now[], n, m, d, cur;
int base[] = {,,,,,,,,,,,};
void init(){
memset(mp, , sizeof(mp));
memset(dp, -, sizeof(dp));
}
/*3进制转10进制*/
int trans(int *t){
int ans = ;
for(int i = ; i <= m; i++)
ans += t[i] * base[i];
return ans;
}
/*10进制转3进制*/
void chan(int t, int *p){
for(int i = ; i <= m; i++)
p[i] = t % , t /= ;
return ;
}
/*i为当前行,j为当前状态,cnt为格子数目,tmp为当前压缩后整行状态*/
void dfs(int i, int j, int cnt, int tmp){
int k;
dp[i & ][tmp] = max(dp[i & ][tmp], cnt);
if(j >= m) return ;
/*放上3行2列的格子
如果该层状态和前一层的状态都允许 也就是都能放格子 那么就放上格子继续搜下去*/
if(!pre[j] && !pre[j + ] && !now[j] && !now[j + ]){
now[j] = now[j + ] = ; //放格子之后状态就都是2了
k = trans(now); dfs(i, j + , cnt + , k);//因为两格都被覆盖,跳过去搜
now[j] = now[j + ] = ; //回溯
}
/*放上2行3列的格子
这个就只跟你当前的状态 也就是i行j列和i-1行j列是否为空 而这一信息仅存储在now[j]上 j+1列 j+2列同理*/
if(j < m - && !now[j] && !now[j + ] && !now[j + ]){
now[j] = now[j + ] = now[j + ] = ; //同样修改 搜下去 回溯
k = trans(now); dfs(i, j + , cnt + , k);
now[j] = now[j + ] = now[j + ] = ;
}
dfs(i, j + , cnt, tmp);
return ;
}
int main(){
int T, x, y;
scanf("%d", &T);
while(T--){
init();
scanf("%d%d%d", &n, &m, &d);
for(int i = ; i <= d; i++){
scanf("%d%d", &x, &y);
mp[x][y] = ;
}
for(int i = ; i <= m; i++)
pre[i] = ;
int tmp = trans(pre);
dp[][tmp] = ; //对于第0行来说,只有啥都不能放这一种状态 将该状态价值为0
for(int i = ; i <= n; i++){
memset(dp[i & ], -, sizeof(dp[i & ])); //初始化本次要用的dp数组
for(int j = ; j < base[m + ]; j++){ //枚举上一行的状态
/* 如果上一行的状态dp数组为-1,说明上一层的该状态根本达不到,那么就不能用来转移*/
if(dp[i + & ][j] == -) continue;
chan(j, pre); //将上一层的状态转换成3进制
for(int k = ; k <= m; k++)
if(mp[i][k]) now[k] = ; //如果此时第k位无法覆盖,那么就为状态为2
/*不然,上层2状态变为1状态,其余为0(根据状态的定义就可以得出)*/
else now[k] = max(pre[k] - , );
cur = dp[i + & ][j]; //cur表示上一层该状态达到的最大价值
dfs(i, , cur, trans(now)); //dfs转移 因为第一格前为第0格不能放,所以状态为1
}
}
int ans = ;
for(int i = ; i < base[m + ]; i++)
ans = max(ans, dp[n & ][i]);
printf("%d\n", ans);
}
return ;
}

用这种多进制表示然后dfs转移的方法可以做出绝大多数的状压题,尤其是状态表示较复杂(一般需要表示两个及以上状态的),转移方程不好写而冗余状态较多的题

比如炮兵阵地,也可以用三进制表示状态然后dfs转移。但是由于炮兵阵地的总状态数并不多,所以可以直接枚举子集,写起来更省力。

洛谷 P1924 poj 1038的更多相关文章

  1. 【洛谷日报#26】GCC自带位运算系列函数

    文章转自 洛谷 谈到GCC的黑科技,大家想到的一定是这句: #pragma GCC optimize (3)//吸氧 抑或是这句: #pragma GCC diagnostic error " ...

  2. 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

    To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...

  3. (洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU - 1007 ) && Raid POJ - 3714

    这个讲的好: https://phoenixzhao.github.io/%E6%B1%82%E6%9C%80%E8%BF%91%E5%AF%B9%E7%9A%84%E4%B8%89%E7%A7%8D ...

  4. POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量

    POJ 1741. Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 34141   Accepted: 11420 ...

  5. tarjan缩点练习 洛谷P3387 【模板】缩点+poj 2186 Popular Cows

    缩点练习 洛谷 P3387 [模板]缩点 缩点 解题思路: 都说是模板了...先缩点把有环图转换成DAG 然后拓扑排序即可 #include <bits/stdc++.h> using n ...

  6. 洛谷 P1731 [NOI1999]生日蛋糕 && POJ 1190 生日蛋糕

    题目传送门(洛谷)  OR 题目传送门(POJ) 解题思路: 一道搜索题,暴力思路比较容易想出来,但是这道题不剪枝肯定会TLE.所以这道题难点在于如何剪枝. 1.如果当前状态答案已经比我们以前某个状态 ...

  7. POJ 1845 (洛谷 :题目待添加)Sumdiv

    约数和 题目描述 给出a和b求a^b的约数和. 输入格式: 一行两个数a,b. 输出格式: 一个数表示结果对 9901 的模. Input 2 3 Output 15 SB的思路: 这是一道典型的数论 ...

  8. 洛谷OJ P1196 银河英雄传说(带权并查集)

    题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山 ...

  9. 【洛谷P2704【NOI2001】】炮兵阵地

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

随机推荐

  1. youtube视频下载和搬运的方法

    youtube全球最大的视频网站, 全世界每天有三分之一的网民在youtube上观看视频, 可是大部分人不知道, 在这些网民有一小部分人是依靠youtube生存的, 他们上传视频到youtube, y ...

  2. TW实习日记:第九天

    这两天有点忙,要改前端网页和加需求上去.所以昨天说的Vue缓存机制也没看,所以打算现在列个挖了的坑的清单: Vue缓存机制.生命周期和钩子函数 使用项目组自用组件来重写静态页面 SSM框架搭建.整合流 ...

  3. 智慧树mooc自动刷课代码

    最近学习javaScript和JQuery,恰好还有一门mooc没有看.结合学习的知识和其他人的代码:撸了一个自动播放课程的代码,同时自动跳过单章的测试题. 用电脑挂着不动就完事了. 如下: var ...

  4. Delphi 中的 RectTracker - 原创

    本文算是副产品,正品是利用 FFmpeg 从任意视频中生成GIF片段的小程序,写完了就发. V2G 正品已出炉,虽然不大像样,但好歹是能用,请见:用 Delphi 7 实现基于 FFMS2 的视频转 ...

  5. 技本功丨收藏!斜杠青年与你共探微信小程序云开发(下篇)

    2019年2月26日,人们为了一个杯子疯了一天. 星巴克猫爪杯,一场已经与猫无关了的“圣杯战争“.网上的倒卖价格,已炒至近千元! 求而不得,舍而不能,得而不惜.这是人最大的悲哀... 所以,请珍惜以下 ...

  6. rz和sz上传下载文件

    安装软件包 yum install  lrzsz   上传文件,输入rz选择文件上传(可以按住shift键多选) # rz   sz 下载文件到本地,选择保存文件夹 # sz dd   xshell设 ...

  7. Hyperledger_Fabric_Model

    Hyperledger_Fabric_Model 本部分描述了Hyperledger Fabric的主要设计特点 Assets: 资产定义使得任何东西都可以通过货币值在网络中交易,从食物到老爷车再到期 ...

  8. sqlmap+tor解决ip黑名单限制

    1.安装tor浏览器(8.0.8)并配置好 旧版tor是需要Vidalia配合的,新版貌似集成了?还是怎样的,反正不需要了 2.启动tor浏览器 3.启动sqlmap python sqlmap.py ...

  9. mysql查看锁表与解锁

    查看锁表语句 show OPEN TABLES where In_use > 0; 找到锁表的进程 show processlist;  删除锁表进程 kill 51045123;

  10. python实现中文验证码识别方法(亲测通过)

    验证码截图如下: # coding:utf-8from PIL import Image,ImageEnhanceimport pytesseract#上面都是导包,只需要下面这一行就能实现图片文字识 ...