POJ 1328
是说在海岸线上怎么样才能见最少的雷达覆盖海中的岛屿,该题转化为数学问题就是在x轴上找最少的点,使之可以覆盖平面上给出的一定数量的点。
思路就是通过找出每个海岛放置雷达的左右区间xl,xr,再按照区间左值xl排序,然后遍历,当发现下一个端点的xl小于前面已经完成的区间最小右值时,计数器加1,维护最小右值即可。找区间的做法就是以海岛为圆心,雷达覆盖的距离为半径,与x轴相交的两点分别是xl,xr。
附上代码以及部分测试数据:
#define MAXN 1005
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef struct
{
int x,y;
}intpoint;//定义储存点的结构体
typedef struct
{
double xl,xr;
}doupoint;//定义储存左右值类型的结构体,double
intpoint lca[MAXN];
doupoint lr[MAXN];
int n,d,counter;
bool cmp(doupoint a,doupoint b)
{
return a.xl<b.xl;
}
bool workout_lr()
{
int i;
double min,te;
for(i=1;i<=n;i++)
{
if(lca[i].y>d || lca[i].y<-1*d)
return false;//遇到不可能的情况,直接跳出
te=sqrt(1.0*(d*d-lca[i].y*lca[i].y));
lr[i].xr=lca[i].x+te;//求出左右值
lr[i].xl=lca[i].x-te;
}
sort(lr+1,lr+n+1,cmp);
counter=1;min=lr[1].xr;
for(i=1;i<=n;i++)
{
if(lr[i].xl>min){//更新并计数
counter++;
min=lr[i].xr;
}
else if(lr[i].xr<min)
min=lr[i].xr;
}
return true;
}
void solve()
{
int i,test=1;
while(scanf("%d %d",&n,&d)==2)
{
if(n==0 && d==0) break;
for(i=1;i<=n;i++) scanf("%d %d",&lca[i].x,&lca[i].y);
//sort(lca+1,lca+n+1,cmp);
printf("Case %d: ",test++);
if(workout_lr()) printf("%d\n",counter);
else printf("-1\n");
}
}
int main()
{
solve();
return 0;
}