雷达设备问题(从另一个角度看待区间合并 + 贪心思路 + 未发现关键的错误样例)

雷达设备问题

文章目录

  • 雷达设备问题
    • 前言
    • 题目描述
    • 题目分析
    • 代码详解
    • 错误案例分析:
    • 思路
    • 代码:

前言

对于区间合并问题,我们一般会将区间按照左端点或者是右端点进行排序,至于其中的选择要依据题目的分析,这里给大家用贪心的想法提供一个例子,帮助大家更深的了解区间合并的应用。喜欢的小伙伴可以点个赞啦!

题目描述

假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。每个小岛都位于海洋一侧的某个点上。雷达装置均位于海岸线上,且雷达的监测范为 d,当小岛与某雷达的距离不超过 d 时,该小岛可以被雷达覆盖。
我们使用笛卡尔坐标系,定义海岸线为 x 轴,海的一侧在 x 轴上方,陆地一侧在 x 轴下方。
现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被达覆盖所需的最小雷达数目。

输入格式
第一行输入两个整数 n 和 d,分别代表小岛数目和雷达检测范围。
接下来 n 行,每行输入两个整数,分别代表小岛的 x,y 轴坐标。
同一行数据之间用空格隔开。

输出格式
输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出 −1。

数据范围
1≤n≤1000, −1000≤x,y≤1000
输入样例:

3 2
1 2
-3 1
2 1

输出样例:

2

题目分析

对于每一个在规定范围内的点,我们都可以将其看成一个区间,如下图:
雷达设备问题(从另一个角度看待区间合并 + 贪心思路 + 未发现关键的错误样例)_第1张图片
每个点都可以转化为这样区间
对于这样的一系列区间,我们是按照他的左端点排序还是按照他的右端点排序呢?
答案是利用 贪心的思路
我们为了用一个雷达获取更多的小岛,理所当然的应该把雷达站安排在小岛的边缘,也就是右端点,看图:
雷达设备问题(从另一个角度看待区间合并 + 贪心思路 + 未发现关键的错误样例)_第2张图片

所以我们按照右端点排序;

代码详解

详细的解析都在代码注释当中啦

#include
#include
#include
using namespace std;
const int N =1e3 + 7;
typedef pair<double,double> PDD;
PDD segs[N];
int n,d;
const double INF=1e9,esp=1e-6;//这里要用double去存储
int main(){
    cin>>n>>d;
    for(int i=1;i<=n;i++){
        int x,y;
        cin>>x>>y;
        if(y>d){//发现不满足要求的点马上排除
            cout<<-1<<endl;
            return 0;
        }
        double len=sqrt(d*d-y*y);
        segs[i]={x+len,x-len};//这里是为了按照右端点进行排序,所以
        //利用字典序的排序手段让右端点在前
    }
    sort(segs+1,segs+n+1);
    double last=-1e9;
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(segs[i].second>last+esp){
        //如果下个区间的左端点大于当前区间右端点,更新区间
            last=segs[i].first;
            cnt++;
        }
    }
    cout<<cnt<<endl;
}

错误案例分析:

思路

这里的代码是没有发现需要将点转化为区间去解决问题,而是仅仅采用贪心的策略,对一个小岛的右侧端点进行找寻,但是忽略了小数位的问题,错误题解中都是int类型的数据,但是正解当中考虑了小数的情况,希望大家引以为戒。
当然,这个题解能过 4/10个数据。

代码:

#include
#include
using namespace std;
const int N =1e3 + 7;

int n,d;
typedef pair<int,int> PII;
PII q[N];
int get_dis(int position,int x,int y){
    return abs(position-x)*abs(position-x)+abs(y*y);
}
int main(){
    cin>>n>>d;
    for(int i=1;i<=n;i++){
        int x,y;
        cin>>x>>y;
        if(y>d){
            cout<<-1<<endl;
            return 0;
        }
        q[i]={x,y};
    }
    sort(q+1,q+n+1);
    int position=q[1].first;
    int cnt=0;
    for(int i=1;i<=n;i++){
        while(get_dis(position,q[i].first,q[i].second)<=d*d){
            position++;
        }
        position--;
        while(get_dis(position,q[i].first,q[i].second)<=d*d && i<=n){
            i++;
        }
        position=q[i].first;
        // cout<<position<<' ';
        cnt++;
        i--;
        
    }
    // puts("");
    cout<<cnt<<endl;
}

你可能感兴趣的:(贪心,算法入门,贪心算法,c++,区间合并)