题目:http://poj.org/problem?id=1328
题意:给定海岛个数,雷达半径,输入各个海岛坐标,求能覆盖所有海岛的最少雷达数
题解:
1. 贪心的区间覆盖问题,尽量让每个雷达覆盖更多岛屿数。
2. 需要将题目转换一下,将海岛坐标,转换为,能够覆盖他的所有雷达圆心的区间, 然后对区间按照起点位置升序排序。
3. 定义一个最右点 end,依次判断所有区间,如果 end < sec[i].start,更新雷达位置,雷达数++;否则如果 end > sec[i].end,更新雷达位置end为sec[i].end。
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <limits>
using namespace std;
int n, d;
const int maxn = 1024 + 20;
struct Section {
double start,
end;
Section(double s = 0, double e = 0) : start(s), end(e) {}
} sec[maxn];
bool cmp(const Section& a, const Section& b) {
return a.start < b.start;
}
void solve()
{
int kase = 0;
while (cin >> n >> d && n)
{
bool flag = true; //false: 不能构成
int ans = 0;
for (int i = 0; i < n; i++)
{
double x, y;
cin >> x >> y;
if (!flag) continue; //前面数据就已经不符合了,没必要再输入了
if (y > d)
{
//y比半径大,一定不可以
flag = false;
continue; //继续输入
}
double dis = sqrt(d * d - y * y);
//能覆盖它的所有雷达的圆心所构成的区间
sec[i].start = x - dis;
sec[i].end = x + dis;
}
if (!flag)
{
printf("Case %d: -1
", ++kase);
continue;
}
sort(sec, sec + n, cmp);
//求double最小值
double end = -numeric_limits<double>::max();
for (int i = 0; i < n; i++)
{
if (end < sec[i].start) {
ans++;
end = sec[i].end;
}
else if (end > sec[i].end) {
end = sec[i].end;
}
}
printf("Case %d: %d
", ++kase, ans);
}
}
int main()
{
solve();
return 0;
}