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

本文深入探讨了大数据开发领域的关键技术,包括Hadoop、Spark、Flink等,并提供了实际应用案例,帮助读者理解如何在大数据环境中高效处理和分析数据。
Bugs Integrated, Inc.
Time Limit: 15000MS Memory Limit: 30000K
Total Submissions: 8789 Accepted: 3372
Case 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

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

Source

 

题意:有一个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 long
const 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();
	}
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值