Fabled Rooks UVA - 11134(贪心,问题分解)

最近做题目感觉贪心题很容易卡壳,就多练练开阔开阔思路吧.
这题开始比较不好想,一个二维的问题很难下手,看了紫书上面说分割成两个一维的问题会简单很多.就稍微有了点思路.和大家分享一下
行和列显然是无关的,因为如果行可以摆,列也可以摆,那么摆到对应的row,col上面就可以了.否则就无解.这是分割的可行性.
那么如何贪心呢?可以这么考虑,每个棋子摆放的区间[l,r].而每一个格子都需要一个棋子,如果在左端点相同的情况下,显然左端点上要放的棋子应该是右边界更小的那一个.这是基本的贪心思想,不过还需要在放完后对当前所有相同左端点的区间做处理.
比如有三个棋子,区间范围为[1,1],[1,2],[1,3],在第一次贪心时候,选的是第一个区间,之后,因为1这个位置已经有棋子了,那么后面两个区间要进行更改,变成[2,2],[2,3].第二次贪心的时候也是一样的处理,但如果说在某个时候,当前需要的格子没有任何一个棋子左边界可以满足.或者修改区间的时候左边界和右边界相等,也就是不能直接或者间接的出现一个区间的l == r(修改之前).就直接return false.
可能有更优秀的解法,这里只是提供一个参考.
这题的思想还是很重要的,分割问题,贪心方法的处理都有启发性.
附上AC代码:

#include <iostream>
#include <cstdio>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int max_n = 1e4 + 10;
int n;
struct line {
	int s, e, num;
	friend bool operator <(line a, line b) {
		if (a.s == b.s) return a.e > b.e;
		else return a.s > b.s;
	}
};
line row[max_n];
line col[max_n];
bool vis[max_n];
int ans[max_n][2];
int judge(line* a, int pos) {
	priority_queue<line> q;
	for (int i = 1; i <= n; ++i) q.push(a[i]);
	int curpos = 1;
	while (!q.empty()) {
		line cur = q.top();
		q.pop();
		if (curpos != cur.s) return 0;
		while (!q.empty() && curpos == q.top().s) {
			line y = q.top();
			q.pop();
			if (y.e == curpos) return 0;
			y.s++;
			q.push(y);
		}
		ans[cur.num][pos] = curpos;
		curpos++;
	}
	return 1;
}
int main() {
//	freopen("as.txt","r",stdin);
	while (cin >> n && n) {
		for (int i = 1; i <= n; ++i) {
			scanf("%d%d%d%d", &row[i].s, &col[i].s, &row[i].e, &col[i].e);
			row[i].num = i;
			col[i].num = i;
		}
		if (judge(row, 0) && judge(col, 1)) {
			for (int i = 1; i <= n; ++i) {
				cout << ans[i][0] << " " << ans[i][1] << endl;
			}
		}
		else cout << "IMPOSSIBLE\n";
	}

	return 0;
}```

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/104345903