B - Radar Installation
题目大意:
描述:
假设海岸线是一条无限长的直线,陆地位于海岸线的一边,大海位于海岸线的另一边。大海中有许多小岛。某安全部门为了监视这些岛上是否有敌人入侵,打算在海岸线上安装若干个雷达来检测岛屿的情况。每个雷达的覆盖范围是以雷达中心为圆心,半径为d的圆形区域。
我们用平面之间坐标系来表示整个区域,海岸线为x轴,大海位于x轴上方,陆地位于x轴下方。为了节约成本,安全部门想使用最少的雷达覆盖所有的岛屿。现在已知每个岛屿的坐标(x,y)和雷达的覆盖半径d,你的任务就是计算出能够覆盖所有岛屿的最少雷达数量。
输入:
输入包含若干组数据。每组数据的第一行有两个整数n(1<=n<=1000)和d,分别表示岛屿的数量和雷达的覆盖半径,之后的n行,每行有两个整数,表示第i个岛屿的坐标(xi,yi),相邻的两组数据使用一个空行隔开。输入“0 0”表示输入结束。
输出:
对于每一组数据的输出格式为“Case i: x”,表示第i组数据中最少需要x个雷达来覆盖所有的岛屿;x=-1表示这组数据无解(无法覆盖所有的岛屿)
解题思路:
其实这是一道区间问题,只要将雷达的位置转为区间来看待就行了。
结合岛屿坐标和雷达覆盖半径,运用勾股定理确定最左和最右的横坐标,以此来确定一个坐标的雷达覆盖区域区间。
cost = sqrt(R*R-y*y);//确定区间
c[i].x1 = x - cost;
c[i].x2 = x + cost;
然后进行排序,从最左边开始寻找公共区域,存在公共区域即可公用一个雷达。
sort(c+1,c+1+n,cmp);//对坐标进行排序
cost = c[1].x2 ;//从最左边的坐标开始寻找
for(i = 2; i <= n; i ++)
{
if(c[i].x1 > cost)//没有公共区域
{
ans ++;
cost = c[i].x2 ;
}
else if(c[i].x2 < cost)//存在公共区域
cost = c[i].x2 ;
}
完整代码如下:
#include<bits/stdc++.h>
using namespace std;
#define N 1100
struct node {
double x1,x2;//储存最左和最右的横坐标
}c[N];
double cmp(struct node a,struct node b)
{
if(a.x1 > b.x1 )
return a.x1 < b.x1 ;
}
int main()
{
int i,j,n,R,ans,t=0;
double x,y,cost;
while(true)
{
scanf("%d%d",&n,&R);
if(n==0 && R==0)break;
ans = 1;
if(R <= 0)//半径小于0显然不符合题意
ans = -1;
for(i = 1; i <= n; i ++)
{
scanf("%lf%lf",&x,&y);
if(fabs(y) > R)//纵坐标大于半径显然也不符合提意
{
ans = -1;
}
else
{
cost = sqrt(R*R-y*y);//确定区间
c[i].x1 = x - cost;
c[i].x2 = x + cost;
}
}
if( ans == -1)
{
printf("Case %d: %d\n",++t,ans);
continue;
}
sort(c+1,c+1+n,cmp);//对坐标进行排序
cost = c[1].x2 ;//从最左边的坐标开始寻找
for(i = 2; i <= n; i ++)
{
if(c[i].x1 > cost)//没有公共区域
{
ans ++;
cost = c[i].x2 ;
}
else if(c[i].x2 < cost)//存在公共区域
cost = c[i].x2 ;
}
printf("Case %d: %d\n",++t,ans);
}
return 0;
}
/*
Sample Input
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
Sample Output
Case 1: 2
Case 2: 1
*/