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. 【Jmeter测试】如何使用CSV Data Set Config获取参数

      Jmeter提供CSV Data Set Config作为参数获取的一种方式​ ​ 1.文件名:csv文件的绝对路径2.文件编码:根据运行环境设置,个人常用的是mac和linux,所以这里选择UT ...

  2. VS2013只显示会附加到进程,无法启动调试

    今天在使用VS2013的时候,打开突然发现,只显示附加到进程,无法进行调试,调试位置显示灰色,到网上各处寻求答案,本以为是个大问题,没想到只是个小问题.主要原因只是后台开太多东西了,导致VS2013运 ...

  3. JSP整理

    JSP全称Java Server Pages,是一种动态网页开发技术.它使用JSP标签在HTML网页中插入Java代码.标签通常以<%开头以%>结束. JSP是一种Java servlet ...

  4. jvm之GC知识点

    GCRoots:        虚拟机栈(栈帧中的局部变量表)引用的对象       方法区中静态属性引用的对象       方法去中常量引用的对象       本地方法栈中JNI(NATIVE方法) ...

  5. 华为笔试——C++消重输出

    题目:消重输出 题目介绍: 输入一个正整数,给出消除重复数字以后最大的整数,注意需要考虑长整数. 例: 输入:988274320 输出:9874320 题目分析:这个结果的实现需要两个步骤:消重和排序 ...

  6. Activity 在横竖屏切换情况下的生命周期变化

    title: Activity 在横竖屏切换情况下的生命周期变化 date: 2018-04-26 23:05:57 tags: [Activity] categories: [Mobile,Andr ...

  7. Centos7 Zabbix监控部署

    Zabbix监控 官方文档 https://www.zabbix.com/documentation/3.4/zh/manual https://www.zabbix.com/documentatio ...

  8. 1014-C程序的语法树

  9. 20181120-4 Beta阶段第2周/共2周 Scrum立会报告+燃尽图 01

    此作业要求参见https://edu.cnblogs.com/campus/nenu/2018fall/homework/2409 版本控制地址   https://git.coding.net/lg ...

  10. 寻找bug

    bug1:void不应有返回值. bug2:while(n--)没有条件终止循环. bug3:size和data没有定义 bug4:arr 是sz 在大于0的情况下创建的 一定部位bull   下面的 ...