贪心算法--雷达安装(poj 1328)

雷达安装

题目描述: 
假定海岸线是一条无限延伸的直线,陆地在海岸线的一边,大海在另一侧。海中有许多岛屿,每一个小岛我们可以认为是一个点。现在要在海岸线上安装雷达,雷达的覆盖范围是d,也就是说大海中一个小岛能被安装的雷达覆盖,那么它们之间的距离最大为d。 
我们使用平面直角坐标系,定义海岸线是x轴,大海在x轴上方,陆地在下方。给你海中每一个岛屿的坐标位置(x,y)和要安装的雷达所覆盖的范围d,你的任务是写一个程序计算出至少安装多少个雷达能将所有的岛屿覆盖。 
输入描述: 
第一行两个整数n(1≤n≤100000)和d,分别表示海中岛屿的数目和雷达覆盖的范围半径d。 
接下来n行,每行两个整数,表示每个岛屿的坐标位置(x,y)。 
输出描述: 
一行一个整数,即能将所有岛屿全部覆盖至少安装的雷达个数,如果无解则输出“-1”。 

样例输入

3 2
1 2
-3 1
2 1

1 2
0 2

0 0

样例输出

Case 1: 2
Case 2: 1

 
数据范围及提示: 
(1≤n≤100000) 
注意会输出-1 
思路: 
贪心思想 
 

贪心算法:

1 ) 将所有区间按照起点从小到大排序,并编号0 - (n-1)

2 ) 依次考察每个区间的起点,看要不要在那里放雷达。开始,所有区间都没被覆盖,所以目前编号最小的未被覆盖的区间的编号 firstNoConverd =0

3 ) 考察一个区间 i 的起点 xi的时候,要看从 firstNoCovered 到区间i-1 中是否存在某个区间 c ,没有被 xi 覆盖。如果没有,则先不急于在xi放雷达,接着往下看。如果有,那么 c 的终点肯定在xi的左边,因此不可能用同一个雷达覆盖 c 和i。即能覆盖c的点,已经不可能覆盖i和i后面的区间了。此时,为了覆盖c,必须放一个雷达了,放在区间 i-1 的起点即可覆盖所有从firstNoCovered到 i-1的区间。因为当初考察 i-1的起点 z时候,并没有发现 z 漏覆盖了从 firstNoCovered 到 i-2 之间的任何一个区间

4) 放完雷达后,将 firstNoCovered改为i,再做下去。 

 这题为贪心题,看到题目,不难想到,如果在岛屿正下方的雷达监测不到岛屿,那该岛屿必定是监测的不到的,在读完该组数据后输出-1即可。因此,对于每一个岛屿,我们以h为半径画圆,如果与x轴没有交点,则该岛无法被监测到,否则,将其与x轴的两个交点存入数组a,b。在所有交点存入数组后,以每个岛的左边的交点为关键字排序。设置一个变量r,为雷达的位置,将排序后的b[1]赋值给r,从第二个岛屿开始找,如果第二个岛屿的靠左的交点在r的监测范围之外,则将雷达数+1,将第二个岛屿靠右的交点赋值给r,如果第二个岛屿的靠右的交点在r的监测范围之内,直接将b[2]赋值给r;依此类推。

#include <iostream>
#include <cmath>#include <algorithm>
#define NUM 1001
using namespace std;
    //n代表小岛数,N代表小岛在island_x轴上的所有区间个数

struct QU_jian
{
    double l;//左边点
    double r;//右边点
    bool operator<(const QU_jian& t)const{
        return this->l<t.l;
    }
}N[NUM];



int main()
{
    int n,d;

    double island_x,island_y;//每一个小岛的坐标
    int k = 1;//案例数

    while(cin>>n>>d&&n&&d){

        int radar_min_num = 1;
        for (int i = 0;i<n;i++){
            cin>>island_x>>island_y;
            if(island_y<=d && d>0 && island_y>=0){
                N[i].r=island_x+(double)sqrt(d*d - island_y*island_y);
                N[i].l=island_x-(double)sqrt(d*d - island_y*island_y);
            }
            else{
                radar_min_num = -1;//读错半径和island_y的坐标继续读
            }
        }
            //用几何关系找到每一个小岛需要固定的半径的雷达在island_x轴上的最大和最小值范围

        sort(N, N+n);
            //对左端的数据从小到大排序


        double temp = N[0].r;
        for( int i = 1;(i<n && radar_min_num != -1);i++){
            if(temp<N[i].l){
                temp = N[i].r;
                radar_min_num++;
            }
            else{
                if(N[i].r<temp)
                    temp = N[i].r;
            }
        }
            //利用贪心算法找到最优
        cout <<"Case "<<k++<<": "<<radar_min_num<<endl;//打印结果
    }
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据您的问题,我理解您想了解POJ1328问题的Java解决方案。POJ1328是一个经典的问题,也被称为"雷达安装"问题,它涉及到在一个二维平面上安装雷达以覆盖所有岛屿的最小雷达数量。以下是一个Java解决方案的示例代码: ```java import java.util.Arrays; import java.util.Comparator; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int caseNum = 1; while (true) { int n = scanner.nextInt(); if (n == 0) { break; } Island[] islands = new Island[n]; for (int i = 0; i < n; i++) { int x = scanner.nextInt(); int y = scanner.nextInt(); islands[i] = new Island(x, y); } int radarNum = getRadarNum(islands); System.out.println("Case " + caseNum + ": " + radarNum); caseNum++; } } private static int getRadarNum(Island[] islands) { Arrays.sort(islands, Comparator.comparingInt(Island::getRight)); int radarNum = 1; int rightMost = islands[0].getRight(); for (int i = 1; i < islands.length; i++) { if (islands[i].getLeft() > rightMost) { radarNum++; rightMost = islands[i].getRight(); } else { rightMost = Math.min(rightMost, islands[i].getRight()); } } return radarNum; } static class Island { private int left; private int right; public Island(int left, int right) { this.left = left; this.right = right; } public int getLeft() { return left; } public int getRight() { return right; } } } ``` 这段代码通过输入岛屿的坐标,计算出需要安装的最小雷达数量,并输出结果。它使用了排序和贪心算法的思想来解决问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_72429728

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值