题目链接:http://poj.org/problem?id=1230
题目大意:魔术师在舞台上表演穿墙术,舞台可视为由若干个单位为一的正方形组成的矩形。输入为n和k,n表示舞台上墙的总数目,k为魔术师的能量,即最多可以穿过k堵墙,接着输入每堵墙的端点坐标(s.x,s.y)、(e.x, e.y),每堵墙长度不定,宽度为1,即s.y=e.y。求最少需要去除多少堵墙才能使魔术师演出顺利。
题目解析:贪心策略。从左到右,依次枚举每一列i,判断当前列的墙的数目x[i]是否大于k,如果大于k,则移除(x[i]-k)个包含当前列且向右延伸最长的墙。需要注意的一点是:输入每堵墙的端点坐标可能会出现e.x > s.x的情况。
程序源码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 110;
struct Node {
int x;
int y;
};
struct Pair {
Node s;
Node e;
}p[MAXN];
int x[MAXN];
bool flag[MAXN];
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
memset(x, 0, sizeof(x));
memset(flag, 0, sizeof(flag));
for (int i = 1; i <= n; i++) {
cin >> p[i].s.x >> p[i].s.y >> p[i].e.x >> p[i].e.y;
if (p[i].s.x > p[i].e.x) {
p[i].s.x ^= p[i].e.x;
p[i].e.x ^= p[i].s.x;
p[i].s.x ^= p[i].e.x;
}
for (int j = p[i].s.x; j <= p[i].e.x; j++) {
x[j]++;
}
}
int ans = 0;
for (int i = 0; i <= 100; i++) {
while (x[i] > k) {
int maxLen = 0, pos = 0;
for (int j = 1; j <= n; j++) {
if ((!flag[j]) && p[j].s.x <= i && p[j].e.x >= i) {
if (maxLen < p[j].e.x) {
maxLen = p[j].e.x;
pos = j;
}
}
}
flag[pos] = true;
ans ++;
for (int j = p[pos].s.x; j <= p[pos].e.x; j++) {
x[j]--;
}
}
}
cout << ans << endl;
}
return 0;
}