贪心
题意:有一个坐标轴,在x轴上可以放半径为r的雷达,x轴上方有n个海岛,给出每个海岛的坐标,问如何用最少的雷达覆盖全部的海岛,如果覆盖不了全部就输出-1。
思路:算出每个海岛可以被扫到的区间,然后根据区间覆盖情况,算出需要的最少雷达。注意区间的左端为x-sqrt(r*r-y*y)右端为x+sqrt(r*r-y*y)。区间越小代表海岛的y坐标越大。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX=1001;
struct Node
{
int x;
int y;
double rang_max;//右端点
double rang_min;//左端点
}p[MAX];
bool cmp(Node a,Node b)
{
return a.x<b.x;
}
int main()
{
int t=1;
int n,r;
while(~scanf("%d%d",&n,&r)&&(n+r))
{
int flag=1;
for(int i=0;i<n;i++)
{
scanf("%d%d",&p[i].x,&p[i].y);
p[i].rang_min=p[i].x-sqrt(r*r*1.0-p[i].y*p[i].y);
p[i].rang_max=p[i].x+sqrt(r*r*1.0-p[i].y*p[i].y);
if(p[i].y>r)//如果海岛y坐标大于雷达半径r,那么雷达就不可能扫到
{
flag=0;
}
}
if(!flag)
{
printf("Case %d: -1\n",t);
t++;
continue;
}
sort(p,p+n,cmp);//将海岛按x坐标从小到大排序
int ans=1;
int k=0;//当前海岛
for(int i=1;i<n;i++)//枚举下一个海岛
{
if(p[k].rang_max<p[i].rang_min)//如果当前海岛的左端点大于所枚举的海岛的右端点的话,那么雷达就可以安在这两个区间之间
{
ans++;
k=i;//改变当前海岛
}
else if(p[k].rang_max>p[i].rang_max)//如果枚举的海岛区间被包含在当前海岛区间的话,说明所枚举的海岛的y大于当前海岛的y,区间范围更小
{
k=i;//改变当前海岛,让其满足那个更小的区间
}
}
printf("Case %d: %d\n",t,ans);
t++;
}
return 0;
}