这道雷达题目是我们大三算法分析与设计考试的最后一个大题。当时写代码用手写的,也没有验证。今天终于验证了我的方法是正确的。题意:笛卡尔坐标系的x轴上安置雷达,使雷达可以覆盖x轴及其上方有若干个岛屿,要求最少使用的雷达数。
思路:要覆盖一个岛屿,雷达的位置可以确定一个范围(以岛屿为圆心,雷达覆盖半径为半径的园和x轴相交形成的切线)。而要使雷达的数目最少,则需要使每一个雷达能覆盖的岛屿的数量尽量的多一些。所以将岛屿以x坐标按升序排列。由左到右遍历岛屿,将范围相交的算作一个雷达,直到找不到范围相交的,再增加雷达数接着将所有范围相交的算在一起。直到遍历完成。此题应该注意的是浮点数的大小比较的时候尽量使用做差之后和零比较大小(计算机组成原理)。还有注意有岛屿的y坐标刚好是雷达覆盖半径的时候的范围比较。还有雷达的覆盖半径不能为负数。
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
struct island
{
int x;
int y;
double left;
double right;
};
struct island isl[1005];
bool cmp_isl(island a,island b)
{
return a.x<b.x;
}
int main()
{
int n,d,casen=0;
while(scanf("%d%d",&n,&d)&&n)
{
casen++;
getchar();
for(int i=0;i<n;i++)
{
scanf("%d%d",&isl[i].x,&isl[i].y);
getchar();
}
getchar();
printf("Case %d:",casen);
sort(isl,isl+n,cmp_isl);
int sum=0;
for(int i=0;i<n;i++)
{
double b = d*d-isl[i].y*isl[i].y;
if(b<0){
sum--;
break;
}
b = sqrt(b);
isl[i].left = isl[i].x-b;
isl[i].right = isl[i].x+b;
}
if(sum<0||d<0) printf(" -1\n");
else if(n==1) printf(" 1\n");
else
{
int t=0;
double l = isl[t].left;
double r = isl[t].right;
t++;
sum++;
while(t<n)
{
bool isok = isl[t].left-l>=0&&isl[t].left-r<=0||isl[t].right-l>=0&&isl[t].right-r<=0;
isok = isok||isl[t].left-l<=0&&isl[t].right-l>=0||isl[t].right-r>=0&&isl[t].left-r<=0;
if(isok)
{
l = isl[t].left>l?isl[t].left:l;
r = isl[t].right<=r?isl[t].right:r;
}else
{
sum++;
l = isl[t].left;
r = isl[t].right;
}
t++;
}
printf(" %d\n",sum);
}
}
return 0;
}