題型:貪心
題意:
有n個點在海里,現在需要用雷達將這些店覆蓋,雷達的輻射範圍是半徑為d的圓,設海岸綫為x軸,雷達要建在x軸上,問最少要多少個雷達能將這些點全部覆蓋。
分析:
既然雷達具有輻射半徑,那麽對於點(x,y),如果y>d,那麽就不可能被覆蓋到,則輸出-1;如果y<=d,那麽雷達安裝的範圍必須在[x-sqrt(d^2-y^2),x+sqrt(d^2-y^2)]區間内。
首先求出每個點所要求的區間,然後按集合右邊界大小進行排序,然後從左邊的集合的右邊界開始找,若該邊界所處集合所屬的點沒有被覆蓋,那麽在這個集合的右邊界檢建一個雷達,然後將集合左邊界處於該雷達左邊的集合刪除,最後貪心下去即可得到答案。
代碼:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define eps 1e-10
#define maxn 1234
using namespace std;
struct point {
double x,y;
} p[maxn];
struct Node{
double l,r;
bool flag;
}h[maxn];
int n;
double d;
bool cmp(Node a,Node b) {
if(fabs(a.r - b.r) < eps)
return a.l < b.l;
return a.r < b.r;
}
double funl(double x,double y) {
return x - sqrt(1.0*d*d-y*y);
}
double funr(double x,double y) {
return x + sqrt(1.0*d*d-y*y);
}
int main() {
int time = 0;
while(1) {
time++;
scanf("%d%lf",&n,&d);
if(n==0 && d==0) break;
for(int i=0; i<n; i++) {
scanf("%lf%lf",&p[i].x,&p[i].y);
}
bool vis = true;
for(int i=0; i<n; i++) {
if(p[i].y > d) {
vis = false;
break;
}
h[i].l=funl(p[i].x,p[i].y);
h[i].r=funr(p[i].x,p[i].y);
h[i].flag=true;
}
if(!vis){
printf("Case %d: -1\n",time);
continue;
}
int ans=0;
sort(h,h+n,cmp);
for(int i=0;i<n;i++){
if(h[i].flag){
ans++;
for(int j=0;j<n;j++){
if(h[j].l < h[i].r+eps && h[j].flag == true){
h[j].flag=false;
}
}
}
}
printf("Case %d: %d\n",time,ans);
}
return 0;
}