POJ 1038 Bug Integrated Inc(状态压缩DP)
Description

Finally, the plate of silicon is cut into memory chips. Each chip consists of 2*3 (or 3*2) unit squares. Of course, no chip can contain any bad (marked) squares. It might not be possible to cut the plate so that every good unit square is a part of some memory chip. The corporation wants to waste as little good squares as possible. Therefore they would like to know how to cut the plate to make the maximum number of chips possible.
Task
You are given the dimensions of several silicon plates and a list of all bad unit squares for each plate. Your task is to write a program that computes for each plate the maximum number of chips that can be cut out of the plate.
Input
Output
Sample Input
2
6 6 5
1 4
4 6
2 2
3 6
6 4
6 5 4
3 3
6 1
6 2
6 4
Sample Output
3
4
思路:
1. 允许的内存为 30000K, 需要使用滚动数组
2. dp[row][state], row 实际取值只有0,1, 使用滚动数组递推, 表示 row, row-1 行的状态为 state 时的最优解(最多的矩形数)
state 一个变量就标出来两行的状态
3. dp[row][state] 由 row, row-1, row-2 三行决定.
<1> row 行的 l 列不可以是坏点
<2> 若是 3*2 的摆放方式, 则 row-1 行, row-2 行, l, l+1, 列不可以被占据
<3> 若是 2*3 ...
void dfs(const int &row, const int &pos, const int &maxNum, const int &s) {
dp[row%2][s] = max(dp[row%2][s], maxNum); // 继承
if(pos >= M) return; // 步长不是1, 所以 == 不行
if(pos<M && !stateCur[pos] && !stateCur[pos+1] && !statePre[pos] && !statePre[pos+1]) {
// 3*2 的矩形
stateCur[pos] = stateCur[pos+1] = 2; // 对下一层来讲, 只需要 stateCur
int k = tri2Ten(stateCur);
dfs(row, pos+2, maxNum+1, k);
stateCur[pos] = stateCur[pos+1] = 0; // 还原
}
if(pos<M-1 && !stateCur[pos] && !stateCur[pos+1] && !stateCur[pos+2]) {
stateCur[pos] = stateCur[pos+1] = stateCur[pos+3] = 2;
int k = tri2Ten(stateCur);
dfs(row, pos+3, maxNum+1, k);
stateCur[pos] = stateCur[pos+1] = stateCur[pos+3] = 0;
}
dfs(row, pos+1, maxNum, s);
}
总结:
1. map[0] 可初始化为全部被占据. 并且, 这也不需要显式赋值, 只需
for(int i = 0; i <= M; i ++)
statePre[i] = map[1][i] + 1;
2. 代码中的 dfs 函数很是精髓. row 是可以当做全局变量, 不需要显式的当做参数. pos 和 maxNum 是必须的, s 主要是为了更新 dp[row%2][s]
3. 最后一步 ans = max(ans, dp[row%2][i]), 可以通过观察发现 row%2 总是最后一行
代码:
#include <iostream>
using namespace std; const int MAXN = 60000;
int tri[12]={0,1,3,9,27,81,243,729,2187,6561,19683,59049}; // 三进制
int testCase, N, M, K;
int statePre[11], stateCur[11];
int map[160][11];
int dp[2][MAXN]; void ten2Tri(int j) {
memset(statePre, 0, sizeof(statePre));
for(int i = 1; i <= M && j; i ++) {
statePre[i] = j % 3;
j /= 3;
}
}
int tri2Ten(const int *p) {
int ans = 0;
for(int i = 1; i <= M; i ++) {
ans += (p[i]*tri[i]);
}
return ans;
}
void pre_process() {
memset(statePre, 0, sizeof(statePre));
memset(stateCur, 0, sizeof(stateCur));
// 初始化第一列 state, 假设第 0 列全被占据
memset(dp, -1, sizeof(dp));
for(int i = 1; i <= M; i ++)
statePre[i] = map[1][i] + 1; dp[1][tri2Ten(statePre)] = 0;
//cout << tri2Ten(statePre) << endl;
}
/*
* 搜寻出每一行所有可能的摆放方式
* 限制条件是该行不可以有坏点
* 需要同时得出所有的 state 值
*/
void dfs(const int &row, const int &pos, const int &maxNum, const int &s) {
dp[row%2][s] = max(dp[row%2][s], maxNum); // 继承
if(pos >= M) return; // 步长不是1, 所以 == 不行
if(pos<M && !stateCur[pos] && !stateCur[pos+1] && !statePre[pos] && !statePre[pos+1]) {
// 3*2 的矩形
stateCur[pos] = stateCur[pos+1] = 2; // 对下一层来讲, 只需要 stateCur
int k = tri2Ten(stateCur);
dfs(row, pos+2, maxNum+1, k);
stateCur[pos] = stateCur[pos+1] = 0; // 还原
}
if(pos<M-1 && !stateCur[pos] && !stateCur[pos+1] && !stateCur[pos+2]) {
stateCur[pos] = stateCur[pos+1] = stateCur[pos+2] = 2;
int k = tri2Ten(stateCur);
dfs(row, pos+3, maxNum+1, k);
stateCur[pos] = stateCur[pos+1] = stateCur[pos+2] = 0;
}
dfs(row, pos+1, maxNum, s);
} int mainFunc() {
for(int row = 2; row <= N; row++) {
for(int j = 0; j < tri[M+1]; j ++) { // 所有可能状态 j
dp[row%2][j] = -1;
}
for(int j = 0; j < tri[M+1]; j++) { // 上一行的所有可能状态 j
if(dp[(row+1)%2][j] == -1) // 无法用来更新, 没有利用价值, 直接跳过
continue;
ten2Tri(j); // 获得 statePre
for(int l = 1; l <= M; l ++) {
if(map[row][l])
stateCur[l] = 2;
else
stateCur[l] = max(0, statePre[l]-1);
}
int pass = dp[(row+1)%2][j];
dfs(row, 1, pass, tri2Ten(stateCur));
}
}
int ans = 0;
for(int i = 0; i < tri[M+1]; i ++)
ans = max(ans, dp[N%2][i]);
return ans;
}
int main() {
freopen("E:\\Copy\\test\\in.txt", "r", stdin);
cin >> testCase;
while(testCase--) {
cin >> N >> M >> K;
memset(map, 0, sizeof(map));
for(int i = 1; i <= K; i ++) {
int a, b;
scanf("%d%d", &a, &b);
map[a][b] = 1;
}
pre_process();
cout << mainFunc() << endl;
}
return 0;
}
POJ 1038 Bug Integrated Inc(状态压缩DP)的更多相关文章
- POJ 1691 Painting a Board(状态压缩DP)
Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat boa ...
- poj 3311 floyd+dfs或状态压缩dp 两种方法
Hie with the Pie Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6436 Accepted: 3470 ...
- POJ 2686_Traveling by Stagecoach【状态压缩DP】
题意: 一共有m个城市,城市之间有双向路连接,一个人有n张马车票,一张马车票只能走一条路,走一条路的时间为这条路的长度除以使用的马车票上规定的马车数,问这个人从a出发到b最少使用时间. 分析: 状态压 ...
- POJ1038 - Bugs Integrated, Inc.(状态压缩DP)
题目大意 要求你在N*M大小的主板上嵌入2*3大小的芯片,不能够在损坏的格子放置,问最多能够嵌入多少块芯片? 题解 妈蛋,这道题折腾了好久,黑书上的讲解看了好几遍才稍微有点眉目(智商捉急),接着看了网 ...
- poj 2411 Mondriaan's Dream_状态压缩dp
题意:给我们1*2的骨牌,问我们一个n*m的棋盘有多少种放满的方案. 思路: 状态压缩不懂看,http://blog.csdn.net/neng18/article/details/18425765 ...
- poj 1185 炮兵阵地 [经典状态压缩DP]
题意:略. 思路:由于每个大炮射程为2,所以如果对每一行状态压缩的话,能对它造成影响的就是上面的两行. 这里用dp[row][state1][state2]表示第row行状态为state2,第row- ...
- POJ 1038 Bugs Integrated, Inc. ——状压DP
状态压缩一下当前各格子以及上面总共放了几块,只有012三种情况,直接三进制保存即可. 然后转移的时候用搜索找出所有的状态进行转移. #include <map> #include < ...
- poj 2411 Mondriaan's Dream(状态压缩dP)
题目:http://poj.org/problem?id=2411 Input The input contains several test cases. Each test case is mad ...
- poj 2686 Traveling by Stagecoach ---状态压缩DP
题意:给出一个简单带权无向图和起止点,以及若干张马车车票,每张车票可以雇到相应数量的马. 点 u, v 间有边时,从 u 到 v 或从 v 到 u 必须用且仅用一张车票,花费的时间为 w(u, v) ...
随机推荐
- win32串口编程
翻译自:ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.WIN32COM.v10.en/dnfiles/html/msdn_serial.htm 老外写的文章, ...
- 基于python的直播间接口测试实战 详解结合项目
基于python的直播间接口测试详解 一.基本用例内容描述 以设置白名单 /advisor/setUserWhiteList.do接口为例,该方法为POST at first,先要导入一些常用到的模块 ...
- LeetCode: Binary Tree Preorder Traversal 解题报告
Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' valu ...
- ucos-III基础教程汇总
目录: 1.ucos-III前言 2.uC/OS-III 概要 3.移植 uC/OS-III 到 STM32 4.调度器 5.uC/OS-III 时钟节拍,时间管理,时间片调度
- MyEclipse9.0激活步骤
MyEclipse 9.0的激活机制 1.破解公钥(确保MyEclipse没有开启,否则失败!) 解压破解包中的myeclipse9_keygen_activator.zip,复制publicKe ...
- 基于css3炫酷页面加载动画特效代码
基于CSS3实现35个动画SVG图标.这是一款基于jQuery+CSS3实现的SVG图标动画代码.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div class=&qu ...
- Hibernate xml配置方法之联合主键
1.StudentPK类,存放Student的联合主键,必须实现java.io.Serializable接口(为了序列化扩充移植),必须重写equals跟hashCode方法(为了确保唯一性) pub ...
- Java SerialPort SDK
SerialPort SDK is a professional java serial port SDK,provides simple communication interface to con ...
- hive中创建表失败
使用create table命令创建表失败,如下错误信息: hive> create table test(id int,name string,age int,sex string); FAI ...
- 试验如何通过审核Google AdSense——我跟谷歌ads杠上啦
http://www.hankcs.com/appos/webhost/apply-google-ads.html —————————————————————————————————————————— ...