状态压缩dp POJ 1038 Bugs Integrated, Inc.

来源:互联网 发布:知错老师 闫春生 编辑:程序博客网 时间:2024/06/04 19:50
Bugs Integrated, Inc.
Time Limit: 15000MS Memory Limit: 30000KTotal Submissions: 8789 Accepted: 3372Case Time Limit: 5000MS

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

26 6 51 44 62 23 66 46 5 43 36 16 26 4

Sample Output

34

Source

CEOI 2002

 

题意:有一个NXM的方格图,你需要放置尽量多的2*3的矩阵块进去,但是有些地方不能占用。给出一个方格图的大小和哪些格子不能占用,问你最多能放多少矩阵块进去。

 

思路:对于一个矩阵块我们有两种放的方法。2*3或者是3*2。那么我们如果要放置一个2*3的,那么上两行对应的格子一定要是空的,如果是3*2,那么上一行的格子一定要是空的。 由于M只有10,我们可以分别用0、1、2来表示每个格子的状态,0表示的时候对应的格子一定是空的(上方的格子也可以是空的),1代表对应的格子以及上一行的对应的格子必须都是空的,然后2表示对应的格子被占用了。那么我们再转移的时候可以放矩阵,也可以不放。那么不放的时候对应的格子的状态应该是0或者1,0可以由上一行同列的格子的状态0或者2推过来 (0包含了1的,所以0比1更优,那就不必考虑1了),1可以由上一行同列的格子的状态0推过来。 如果要放矩阵,那么当前行放矩阵的地方对应的格子都是2,而上一行的对应的同列的格子的状态可以是全都是0(3*2),也可以全都是1(2*3)。 基本就是这样了。具体可以看代码

 

#include<cstdio>#include<string.h>#include<vector>#include<iostream>#include<cmath>using namespace std;#define LL long longconst int maxn = 59049 + 5;const int inf = 1e8;int n, m, k;int dp[2][maxn];bool ocp[155][16];bool ok1[155][15];bool ok2[155][15];//0:一定空 1:两个空 2:被填了。int p[12],S[12];inline int max(int a, int b) { return a > b ? a : b; }void input(){scanf("%d%d%d", &n, &m, &k);memset(ocp, 0, sizeof(ocp));while (k--) {int r, c; scanf("%d%d", &r, &c);--r, --c;ocp[r][c] = true;}}void out(int s){printf("%d\n", s);int a = m;while (s > 0) {printf("%d", s % 3);s /= 3;--a;}if (a < 0)char a = 'a';while (a--) printf("0");puts("");}int cur;void dfs(int row, int col, int to, int from, int v){//out(from); out(to);if (col > m) return;if (col == m) {if (dp[cur^1][from] + v > dp[cur][to])dp[cur][to] = dp[cur^1][from] + v;//dp[row][to] = max(dp[row][to], dp[row - 1][from] + v);return;}//不放:if (!ocp[row][col]) {dfs(row, col + 1, to, from + 2 * p[col], v);if (!ocp[row - 1][col]) {dfs(row, col + 1, to, from, v);dfs(row, col + 1, to + p[col], from, v);}}else {dfs(row, col + 1, to + 2 * p[col], from + 2 * p[col], v);if (!ocp[row - 1][col])dfs(row, col + 1, to + 2 * p[col], from, v);return;}//横放:if (ok1[row][col]) {int s_to = to, s_from = from;for (int j = col; j <= col + 2; ++j) s_to += 2*p[j];dfs(row, col + 3, s_to, s_from, v + 1);}//竖放:if (ok2[row][col]) {int s_to = to, s_from = from;for (int j = col; j <= col + 1; ++j) s_to += 2 * p[j], s_from += p[j];dfs(row, col + 2, s_to, s_from, v + 1);}}void solve(){for (int r = 0; r < n; ++r) {for (int c = 0; c < m; ++c) {ok1[r][c] = ok2[r][c] = true;if (r - 1 < 0 || c+2>=m) ok1[r][c] = false;else {for (int i = r - 1; i <= r;++i)for (int j = c; j <= c + 2;++j) if (ocp[i][j]) ok1[r][c] = false;}if (r - 2 < 0 || c + 1 >= m) ok2[r][c] = false;else {for (int i = r - 2; i <= r;++i)for (int j = c; j <= c + 1;++j) if (ocp[i][j]) ok2[r][c] = false;}}}int s = 0;fill(dp[0], dp[0] + p[m] + 1, -inf);for (int j = 0; j < m; ++j) {if (ocp[0][j]) s += 2*p[j];}dp[0][s] = 0;cur = 1;for (int i = 1; i < n; ++i) {fill(dp[cur], dp[cur] + p[m] + 1, -inf);dfs(i, 0, 0, 0, 0);cur ^= 1;}int ans = 0;for (int j = 0; j < p[m];++j) if (ans < dp[cur^1][j]) ans = dp[cur^1][j];printf("%d\n", ans);}int main(){p[0] = 1;for (int i = 1; i <= 10; ++i) p[i] = 3 * p[i - 1];int T; cin >> T;while (T--) {input();solve();}}


 

 

0 0
原创粉丝点击