题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=287
这题从昨天晚上开始做,今天才做出来,果然还是不熟练啊。
题目大意:其实有个图加上测试数据就很好理解了,x轴为海岸,x轴以上为海,海上有岛屿,在海岸上安置雷达,给出各个岛屿的坐标和雷达覆盖的半径。如果能全部覆盖则输出需要最少雷达数量,如果不能完全覆盖则输出-1。
思路:其实还是贪心思想,顺便用到数学图形,这次以点为辐射,以半径r画园,判断园与x轴的交点。如果没有交点说明一定不能完全覆盖,否则求出两个交点的坐标。把交点的左坐标从小到大排序,需要处理的是如果有包含的情况。
代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct dy
{
double left;//**左交点**//
double right;//**右交点**//
}w[1001];
bool comp(dy a,dy b)//**按左交点坐标从小到大排序**//
{
if(a.left<b.left) return true;
return false;
}
int main()
{
int n,r,x,y,i,count,num=1;
double len,t;
while(~scanf("%d %d",&n,&r)&&(n,r))
{
memset(w,0,sizeof(w));
count=1;//**从第一个点开始,所以计数器初值为1**//
for(i=0;i<=n-1;i++)
{
scanf("%d %d",&x,&y);
len=sqrt(((double)r*r-(double)y*y));//**结合图形,勾股定理**//
w[i].left=(double)x-len;//**左交点的坐标**//
w[i].right=(double)x+len;//**右交点的坐标**//
}
for(i=0;i<=n-1;i++)
{
if(y>r)//**如果不能完全覆盖**//
{
printf("Case %d: -1\n",num++);
break;
}
}
sort(w,w+n,comp);
t=w[0].right;
for(i=1;i<=n-1;i++)
{
if(w[i].left>t)//**如果后一个点的左交点大于前一个点的右坐标,说明两点没有公共区域**//
{
count++;
t=w[i].right;
}
else
{
if(w[i].right<t)//**如果后一个点的右交点小于前一个点的右坐标,说明后一个点的覆盖区域被前一个点包含了**//
{
t=w[i].right;//**保证后一个点被覆盖**//
}
}
}
printf("Case %d: %d\n",num++,count);
}
return 0;
}