题目链接:https://cn.vjudge.net/problem/ZOJ-1360
思路: 转化为区间问题,对每个岛屿,求出可以观测到它的雷达的放置区段,比如d=5,(x,y)=(0,4),则雷达可以放置在x∈[-3 ,3]这个区段上。求出所有区段后,按区段的左端点从大到小排序,若第i个区段的右端点大于第i+1个区段的左端点,那么这两个区段对应的岛屿可以用同一个雷达观测到(覆盖)。
比如此7个区段,用3个雷达就可以全部覆盖
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1005;
struct Island {
double x,y; // 岛屿坐标
}Islands[maxn];
struct Block
{
double l,r; // 记录区段的左右端点的x坐标
friend bool operator < (const Block &t1,const Block &t2) {
return t1.l < t2.l;
}
}Blocks[maxn];
double Maxdis(double y,double d) // 用于计算在可以覆盖岛屿的情况下,雷达与岛屿的x方向最远距离;
{
return sqrt(d*d - y*y);
}
int main()
{
int n;
double d;
int Case = 1;
int sum,flag;
while(scanf("%d %lf",&n,&d) && n) {
flag = 0;
sum = 0;
for(int i=1;i<=n;i++) {
scanf("%lf %lf",&Islands[i].x,&Islands[i].y);
if(abs(Islands[i].y) > d)
flag = 1;
}
if(flag) {
printf("Case %d: -1\n",Case++);
continue;
}
//为每个岛屿找雷达放置的区段
double dis;
for(int i=1;i<=n;i++) {
dis = Maxdis(Islands[i].y,d);
Blocks[i].l = Islands[i].x - dis;
Blocks[i].r = Islands[i].x + dis;
}
sort(Blocks+1,Blocks+n+1);
double MinR; // 当前雷达放置所有区段的最小右端点
for(int i=1;i<=n;) {
sum++;
MinR = Blocks[i].r;
int j;
for(j=i+1;j<=n;j++) {
if(Blocks[j].l <= MinR) {
if(Blocks[j].r < MinR)
MinR = Blocks[j].r;
}
else
break;
}
i = j;
}
printf("Case %d: %d\n",Case++,sum);
}
}