【贪心算法c++】---洛谷|P1325 安装雷达

题目:
描述:

假设海岸线是一条无限延伸的直线。它的一侧是陆地,另一侧是海洋。每一座小岛是在海面上的一个点。雷达必须安装在陆地上(包括海岸线),并且每个雷达都有相同的扫描范围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;
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值