POJ 1089 Intervals
POJ 1089【Intervals】题目链接:
思路
我们可以使得每个雷达尽可能多的覆盖小岛。我们可以枚举每个小岛求出能覆盖当前小岛的雷达放置位置的区间,从左往右看,为了尽量不浪费雷达的检测范围,对于第一个雷达,为了不浪费雷达的检测范围,所以将第一个雷达放在第一个放置区间的最右端,然后依次枚举下一个小岛,取前两个小岛的放置区间的交集,直到出现第一个小岛的放置区间不在当前交集区间内,则新增雷达。所以此时根据性质,可以将放置区间按区间右端点排序,则不需要对区间进行单独讨论了,只需要确定一个右端点为依次遍历直到找出第一个放置区间左端点大于交集区间右端点的小岛,此时则将交集区间更新为这个小岛的放置区间,即为新放置一个雷达,依次枚举遍历所有的小岛。
代码
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
#define ll long long
const int N = 1e5 + 10;
ll n, m, flag;
pair<double , double> site[N];
pair<double, double> segment[N];
bool cmp(pair<double, double> a, pair<double, double> b) { return a.second < b.second; }
int main() {
ll t = 0;
while (cin >> n >> m) {
t++;
flag = 0;
if (n == 0 && m == 0) {
break;
}
for (int i = 1; i <= n; i++) {
cin >> site[i].first >> site[i].second;
if (site[i].second > m) {
flag = 1;
}
}
if (flag) {
cout << "Case " << t << ": -1" << endl;
continue;
}
for (int i = 1; i <= n; i++) {
// 找出线段半径
double x = sqrt((double)m * (double)m - (double)site[i].second * (double)site[i].second);
segment[i].first = site[i].first - x, segment[i].second = site[i].first + x;
}
sort(segment + 1, segment + 1 + n, cmp);
int num = 1;
double r = segment[1].second;
for (int i = 2; i <= n; i++) {
if (r < segment[i].first) {
r = segment[i].second;
num++;
}
}
cout << "Case " << t << ": " << num << endl;
}
return 0;
}