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 老外写的文章, ...
- SVN开启端口监听,并设置开机启动
svnserve -d -r /home/svn/repo --listen-port=3690,svn仓库地址,及监听端口 vi svn_startup.sh,位置在/root下面编辑一个启动脚本, ...
- tomcat Can't create cache file!
) at javax.imageio.ImageIO.write(ImageIO.java:1558) ... 119 more Caused by: java.io.IOException: 系统找 ...
- QDialog:输入对话框、颜色对话框、字体对话框、文件对话框
# _*_ coding:utf-8 _*_ import sys from PyQt4 import QtCore,QtGui class Example(QtGui.QWidget): def _ ...
- dp:FZU2030括号问题
http://acm.fzu.edu.cn/problem.php?pid=2030 给出一个字符串,其中包括3种字符: ‘(‘, ‘)’, ‘?’.其中?表示这个字符可以是’(‘也可以是’)’. 现 ...
- 基于jQuery/CSS3实现拼图效果的相册插件
今天我们要来分享一款很酷的jQuery相册插件,首先相册中的图片会以一定的角度倾斜放置在页面上,点击图片缩略图就可以展开图片,并且图片是由所有缩略图拼接而成,图片展开和收拢的动画效果也非常不错.当然图 ...
- 一款html拼图游戏详解
本文是爱编程原创翻译,转载请看清文末的转载要求,谢谢合作! 游戏介绍 这篇文章是献给web游戏开发者用简单的开发工具开发一款游戏.此文介绍了用html.css.javascript只需简单和几个步骤开 ...
- Gradle 庖丁解牛(构建生命周期核心托付对象创建源代码浅析)
[工匠若水 http://blog.csdn.net/yanbober 未经同意严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 上一篇<Gradle 庖丁解牛(构建源头源代码浅析)> ...
- 使用平台调用(P/Invoke)
使用平台调用 P/Invoke.它的全名叫平台调用(platform invoke).用于调用dll 中实现的非托管的单调(flat)编程接口.被称为使用C或C++ 调用约定(calling conv ...
- Entity Framework应用:管理并发
理解并发 并发管理解决的是允许多个实体同时更新,实际上这意味着允许多个用户同时在相同的数据上执行多个数据库操作.并发是在一个数据库上管理多个操作的一种方式,同时遵守了数据库操作的ACID属性(原子性. ...