Radar Installation POJ - 1328 (区间贪心)

本文解析了一道基于区间贪心算法的题目,介绍了如何通过逆向思维将问题转化为求最少的点以覆盖所有线段的问题,并给出了具体的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://vjudge.net/problem/POJ-1328

一道比较基础的贪心题目, 比较巧妙的是题中用到了区间贪心的算法.

起初看题的时候一直有一个误区, 总想通过分析雷达关于岛的位置来确定范围, 后来发现其实加上一点儿逆向思维, 通过考虑岛来确定雷达的范围其实会更简单

具体来说, 考虑一下每个小岛被覆盖时雷达的区间, 最后就把各个小岛转化为了一个个区间, 我们的任务就是求最少的点, 使得所有的线段都被覆盖到, 直接顺序枚举+贪心即可

具体的贪心算法就是对于每个岛不断的和下一个岛判断是否有交集, 有的话再判断是否改变集合的边界(也就是真子集与否的判断)

//建立雷达 贪心
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 1010;
struct Island{
    double left, right;
}isl[maxn];
bool operator < (const Island &a, const Island &b)
{
    return a.left < b.left; //升序
}
int n, d, x, y;
int solve()
{
    sort(isl+1, isl+1+n); //按左端点大小升序排列
    //若当前线段与目前集合中的线段没有交集, 则加入新的雷达
    double range = isl[1].right; int ans = 1;
    for(int i = 2; i <= n; i++){
        if(isl[i].left <= range) range = min(range, isl[i].right);
        else range = isl[i].right, ans++;
    }
    return ans;
}


int main()
{
    int index = 1;
    while(scanf("%d%d",&n,&d)==2 && (n!=0||d!=0)){
        bool flag = 1;
        memset(isl, 0, sizeof(isl)); //初始化
        for(int i = 1; i <= n; i++){
            scanf("%d%d",&x,&y);
            if(y > d) flag = 0;
            isl[i].left = x - sqrt(d*d-y*y); //计算每个小岛决定的雷达范围
            isl[i].right = x + sqrt(d*d-y*y); //勾股定理
        }
        if(flag) printf("Case %d: %d\n",index++, solve());
        else printf("Case %d: -1\n",index++); //剪枝
    }
    return 0;
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值