题目:
描述:
假设海岸线是一条无限延伸的直线。它的一侧是陆地,另一侧是海洋。每一座小岛是在海面上的一个点。雷达必须安装在陆地上(包括海岸线),并且每个雷达都有相同的扫描范围d。你的任务是建立尽量少的雷达站,使所有小岛都在扫描范围之内。
数据使用笛卡尔坐标系,定义海岸线为x轴。在x轴上方为海洋,下方为陆地。
样例1如图所示
输入格式
第一行包括2个整数n和d,n是岛屿数目,d是雷达扫描范围。
接下来n行为岛屿坐标。
输出格式
一个整数表示最少需要的雷达数目,若不可能覆盖所有岛屿,输出“-1”。
输入输出样例
输入 复制
3 2
1 2
-3 1
2 1
输出 复制
2
思路:
我们可以把雷达的覆盖范围,转换为岛屿的覆盖范围,它们的扫描半径都是d,每个岛屿的扫描范围是一个半径为d的圆面,那么根据题意,他们必定与x周相交,求出每个岛屿的面面与x周的两个交点,这样就转换成了一个线段覆盖的问题,只要是两个线段有重合,就可以公用一个雷达,要是两个线段没有重合,那雷达数就加一
上代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int n,d;
struct IsLand///一开始存住岛屿左边,之后存储圆面与x轴交点的左右端点
{
double x;
double y;
} isLands[1000];
void point(IsLand &is)///计算左右端点
{
double a = sqrt(d*d - is.y*is.y) + is.x;
double b = sqrt(d*d - is.y*is.y)*-1 + is.x;
is.x = b;
is.y = a;
}
int cmp(IsLand a, IsLand b)///按每个线段的右端点从小到大排序
{
if(a.y==b.y)
return a.x<b.x;
else
return a.y<b.y;
}
int main()
{
cin>>n>>d;
for(int i=0; i<n; i++)
{
double a,b;
cin>>a>>b;
if(b>d)
{
cout<<-1;
return 0;
}
isLands[i].x =a;
isLands[i].y =b;
point(isLands[i]);
}
sort(isLands,isLands+n,cmp);
int sum = 1,flag = 0;
for(int i=1; i<n; i++)
{
if(isLands[i].x<=isLands[flag].y)///看是否有重合部分
continue;
sum++;
flag = i;
}
cout<<sum<<endl;;
return 0;
}