【贪心算法】POJ1328

【贪心算法】POJ1328

题目:http://poj.org/problem?id=1328

思路

假设有n个小岛,我们按照每个小岛为圆心画一个半径为d的圆形,这个圆形会割x轴,形成一个区间,我们记它为 [ l i , r i ] [l_i,r_i] [li,ri],即如果雷达安装在这个区间中,这个小岛就被雷达覆盖了。
那么这么一来,我们就将原题目化简为:

假设存在n个区间: [ l i , r i ] [l_i,r_i] [li,ri],我们向区间中散"芝麻",为确保每个区间中至少存在一粒芝麻,请问最少需要多少粒芝麻?

化简以后,这是典型的贪心算法,我们不妨将n个区间,按照 l i l_i li进行排序,确保 l i ≤ l j   ( i < j ) l_i\le l_j\space (i<j) lilj (i<j)
我们假设最开始在 I 1 I_1 I1中有一粒芝麻, I 1 = [ l 1 , r 1 ] I_1=[l_1,r_1] I1=[l1,r1], I 2 = [ l 2 , r 2 ] I_2=[l_2,r_2] I2=[l2,r2],则它们两的关系只有3种

  1. l 2 > r 1 l_2>r_1 l2>r1,即此时两区间不相交,这时 I 1 I_1 I1是一个separate的,(因为对于 I 3 , I 4 , . . . I_3,I_4,... I3,I4,...,它们都和 I 1 I_1 I1不相交),则我们需要新增一粒芝麻放在 I 2 I_2 I2中,并且此时我们已经不关心 I 1 I_1 I1了,我们将它抛弃。
  2. l 2 ≤ r 1 且 r 2 ≤ r 1 l_2\le r_1 且r_2\le r_1 l2r1r2r1,这时 I 1 I_1 I1包含 I 2 I_2 I2,这时我们不需要新增芝麻,只需将原来在 I 1 I_1 I1中的芝麻,移动到 I 2 I_2 I2中,就行了,而且此时我们也要抛弃 I 1 I_1 I1,因为芝麻只能在 I 2 I_2 I2中移动
  3. l 2 ≤ r 1 且 r 2 > r 1 l_2\le r_1且r_2>r_1 l2r1r2>r1,此时 I 1 I_1 I1 I 2 I_2 I2应该是交错的,我们也不需要新增芝麻,只需将 I 1 I_1 I1中的芝麻移动到 [ l 2 , r 1 ] [l_2,r_1] [l2,r1]中,这时我们需要抛弃 I 2 I_2 I2,保留 I 1 I_1 I1,而此时我们可以认为 I 1 = [ l 2 , r 1 ] I_1=[l_2,r_1] I1=[l2,r1],不过这无关紧要,因为 [ l 1 , r 1 ] 还是 [ l 2 , r 1 ] [l_1,r_1]还是[l_2,r_1] [l1,r1]还是[l2,r1]对于后续的区间 I 3 , I 4 , . . . I_3,I_4,... I3,I4,...来说根本无所谓,反正 l 3 ≥ l 2 l_3\ge l_2 l3l2正如 l 3 ≥ l 1 l_3\ge l_1 l3l1

对于以上三种情况,只有情况1需要新增芝麻粒,情况1和2需要抛弃 I 1 I_1 I1,而只有情况3我们需要抛弃 I 2 I_2 I2

代码

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

typedef struct Interval
{
    double l;
    double r;
}Interval;

bool comp(Interval a,Interval b)
{   
    return (a.l<b.l);
}
int main()
{
    int n,d;
    int index=0;
    while(cin>>n>>d)
    {
        if(n==0 && d==0)
        {
            break;
        }
        index++;
        cout<<"Case "<<index<<": ";
        Interval a[n];
        int x,y;
        bool flag=false;
        for(int i=0;i<n;i++)
        {
            cin>>x>>y;
            if(y>d)
            {
                flag=true;
            }
            else
            {
                a[i].l=(double)x-(double)sqrt((double)(d*d-y*y));
                a[i].r=(double)x+(double)sqrt((double)(d*d-y*y));
            }
        }
        if(flag)
        {
            cout<<-1<<endl;
        }
        else
        {
            sort(a,a+n,comp);
            int sum=1;
            double r1=a[0].r;
            for(int i=1;i<n;i++)
            {
                if(a[i].l>r1)
                {
                    sum++;
                    r1=a[i].r;
                }
                else
                {
                    if(a[i].r<=r1)
                    {
                        r1=a[i].r;
                    }
                    else
                    {
                        //nothing
                    }
                }
            }
            cout<<sum<<endl;
        }

    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值