112. 雷达设备(贪心)

https://www.acwing.com/problem/content/114/
典型区间贪心
题目要求寻找最少雷达摆放数,范围覆盖所有岛
读题后一开始想的是雷达放在x轴何处,但是这样直接想太难了,而且有关于圆的操作,不利于判断
于是转换角度(改变主体),从岛的角度看,雷达可以摆在x轴的那些地方,这样就变成区间了
即,我们不考虑每个雷达可以覆盖哪些小岛,而是每个小岛可以在哪些区间摆放雷达
对于每一个岛,雷达摆放在x轴上都有一个区间,只要不超过区间,就可以覆盖到岛

那么问题就转变为求给定若干区间,求最少需要多少点,可以满足所有区间都包含点

那么有n个岛,就有n个区间,将n个区间以右端点排序,区间之间有的有交集,有的没有
有交集的就说明在这个交集内,雷达可以覆盖这两个岛
贪心策略:
对于每个区间:
1.要是上一个点不在此区间范围内,就说明上一个区间和此区间没有交集,必然要用两个点去覆盖这两个区间,放右端点
2.要是上一个点在此区间范围内,说明这个区间以及被满足条件了,则跳到下一区间继续判断

严格证明:
这里利用通用的证明方式:cnt表示这个算法的结果,opt表示最佳解,我们的目标是证明cnt=opt.
通用的证明等于的方式,即要证明cnt>=opt且cnt<=opt
根据定义,显然有1.opt<=cnt,我们算法的解一定是大于等于最佳解的,这个式子一定成立
2.证明opt>=cnt,即等价于证明 所有可行解>=cnt (放缩,opt是所有解的子集)
根据我们的贪心策略,上一个点所在的区间必定是在现在区间的左端点左边,即两个区间不相交
若我们选了cnt个点:就说明存在cnt个不相交的区间
有cnt个互不相交的区间,因为要满足所有区间都要包含点,区间之间没有交集,无法共用一个点,于是我们的点数必定>=cnt,至少为cnt个
故得证,所有可行解必然>=cnt,故opt必然>=cnt
故证cnt=opt

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1e3+10;
int n,d;
int x,y;
int cnt;
struct line
{
    double l,r;
}l[N];

bool cmp(line a,line b)
{
    return a.r<b.r;
}

int main()
{
    cin >> n >> d;
    for(int i=0;i<n;i++)
    {
        cin >> x >> y;
        double width=sqrt(d*d-y*y);
        l[i]={x-width,x+width};
        if(y>d)
        {
            cout << -1 << endl;
            return 0;
        }
    }
    sort(l,l+n,cmp);
    double last = -1e4;
    for(int i=0;i<n;i++)
    {
        if(l[i].l>last)
        {
            last=l[i].r;
            cnt++;
        }
    }
    cout << cnt << endl;
    return 0;
}




posted @   风乐  阅读(24)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示