Description

Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launching production of a new six terabyte Q-RAM chip. Each chip consists of six unit squares arranged in a form of a 2*3 rectangle. The way Q-RAM chips are made is such that one takes a rectangular plate of silicon divided into N*M unit squares. Then all squares are tested carefully and the bad ones are marked with a black marker. 

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

The first line of the input file consists of a single integer D (1 <= D <= 5), denoting the number of silicon plates. D blocks follow, each describing one silicon plate. The first line of each block contains three integers N (1 <= N <= 150), M (1 <= M <= 10), K (0 <= K <= MN) separated by single spaces. N is the length of the plate, M is its height and K is the number of bad squares in the plate. The following K lines contain a list of bad squares. Each line consists of two integers x and y (1 <= x <= N, 1 <= y <= M) ?coordinates of one bad square (the upper left square has coordinates [1, 1], the bottom right is [N,M]).

Output

For each plate in the input file output a single line containing the maximum number of memory chips that can be cut out of the plate.

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)的更多相关文章

  1. POJ 1691 Painting a Board(状态压缩DP)

    Description The CE digital company has built an Automatic Painting Machine (APM) to paint a flat boa ...

  2. poj 3311 floyd+dfs或状态压缩dp 两种方法

    Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6436   Accepted: 3470 ...

  3. POJ 2686_Traveling by Stagecoach【状态压缩DP】

    题意: 一共有m个城市,城市之间有双向路连接,一个人有n张马车票,一张马车票只能走一条路,走一条路的时间为这条路的长度除以使用的马车票上规定的马车数,问这个人从a出发到b最少使用时间. 分析: 状态压 ...

  4. POJ1038 - Bugs Integrated, Inc.(状态压缩DP)

    题目大意 要求你在N*M大小的主板上嵌入2*3大小的芯片,不能够在损坏的格子放置,问最多能够嵌入多少块芯片? 题解 妈蛋,这道题折腾了好久,黑书上的讲解看了好几遍才稍微有点眉目(智商捉急),接着看了网 ...

  5. poj 2411 Mondriaan's Dream_状态压缩dp

    题意:给我们1*2的骨牌,问我们一个n*m的棋盘有多少种放满的方案. 思路: 状态压缩不懂看,http://blog.csdn.net/neng18/article/details/18425765 ...

  6. poj 1185 炮兵阵地 [经典状态压缩DP]

    题意:略. 思路:由于每个大炮射程为2,所以如果对每一行状态压缩的话,能对它造成影响的就是上面的两行. 这里用dp[row][state1][state2]表示第row行状态为state2,第row- ...

  7. POJ 1038 Bugs Integrated, Inc. ——状压DP

    状态压缩一下当前各格子以及上面总共放了几块,只有012三种情况,直接三进制保存即可. 然后转移的时候用搜索找出所有的状态进行转移. #include <map> #include < ...

  8. poj 2411 Mondriaan's Dream(状态压缩dP)

    题目:http://poj.org/problem?id=2411 Input The input contains several test cases. Each test case is mad ...

  9. poj 2686 Traveling by Stagecoach ---状态压缩DP

    题意:给出一个简单带权无向图和起止点,以及若干张马车车票,每张车票可以雇到相应数量的马. 点 u, v 间有边时,从 u 到 v 或从 v 到 u 必须用且仅用一张车票,花费的时间为 w(u, v) ...

随机推荐

  1. npm 的指令介绍

    npm install <name>安装nodejs的依赖包 例如npm install express 就会默认安装express的最新版本,也可以通过在后面加版本号的方式安装指定版本, ...

  2. 深入理解Eureka - Eureka Client获取注册信息机制

    深入理解Eureka - Eureka Client获取注册信息机 Eureka Client提供了定时获取注册信息的机制.Eureka Client获取注册信息的所有逻辑都在DiscoveryCli ...

  3. LeetCode: Word Break II 解题报告

    Word Break II Given a string s and a dictionary of words dict, add spaces in s to construct a senten ...

  4. 纯绿色 jsonUtil工具

    package com.daditech.common.util; import java.lang.reflect.Field; import java.lang.reflect.Method; i ...

  5. android中activity向service中传值

    和activity中互相传值类似 在activity中 Intent regIntent = new Intent(this, ChatService.class);  regIntent.putEx ...

  6. Activiti 获取定义

    ProcessDefinitionEntity d = (ProcessDefinitionEntity)((RepositoryServiceImpl)repositoryService).getD ...

  7. Hbase 学习(二)各种filter

    各种filter 今天的主题是Filter,hbase客户端查询的时候,自定义查询filter. 直接上例子吧,不多说别的了,第一个例子是RowFilter的. Scan scan = new Sca ...

  8. IE6、IE7、IE8、Firefox兼容性

    整理关于IE6.IE7.IE8.Firefox兼容性CSS HACK问题 1.区别IE和非IE浏览器CSS HACK代码 #divcss5{background:blue; /*非IE 背景藍色*/b ...

  9. elasticsearch安装与使用(4)-- 安装中文分词插件elasticsearch 的 jdbc

    前言 elasticsearch(下面简称ES)使用jdbc连接mysql比go-mysql-elasticsearch的elasticsearch-river-jdbc能够很好的支持增量数据更新的问 ...

  10. iOS彩票项目--第五天,新特性引导页的封装、返回按钮的自定义、导航控制器的滑动返回以及自定义滑动返回功能

    一.上次实现了在AppDelegate中通过判断app版本决定是否进入新特性页面,今天将AppDelegate中的一坨进行了封装.将self.window的根控制器到底应该为新特性界面,还是主页面,封 ...