zoukankan      html  css  js  c++  java
  • POJ1328贪心

    题意:如今我们位于沿海地区,需要安装大炮,使得火力可以覆盖整个区域。海岸线可以视为是无限长的直线。陆地位于海岸线的一侧,海洋位于另一侧。海洋里有若干个岛屿,每个小岛可以视为海洋中的一个点。我们需要在海岸线上安装大炮,每个大炮智能覆盖距离d,因此海洋中的小岛被大炮安装所覆盖的条件是两者间的距离不超过 d 。 我们将海岸线视为 x 轴。海洋的一侧位于 x 轴上方,陆地的一侧位于下方。给定海洋中每个小岛的位置(以xy坐标给出),并给定大炮的覆盖距离,你需要写程序,找出安装大炮的最少数量,使得所有的小岛都被覆盖。

    题解:我们先将所有的岛屿视为圆心,以半径d做圆,如果最远距离大于d的,直接视为无法完全覆盖,输出-1;

    如果全部可以覆盖,则可以认为x轴对于圆的割线就是满足题意的炮台位置,此时本题就转化为了贪心问题中的基操——区间选点问题

    区间选点问题的题型:n个区间[ai,bi],在数轴上选取尽可能少的点,能保证每段区间上都能有一个点。

    区间选点的贪心策略:右端点从小到大排序,如果右端点相同则左端点从大到小排序

    贪心过程:标记第一个右端点为r,不断向后与下一段的左端点开始比较,如果下一段的左端点大于r,则更新r,否则一直向后找


    #include<stdio.h>
    #include<algorithm>
    #include<iostream>
    #include<math.h>
    using namespace std;
    
    struct node {
        double x;
        double y;
    }island[1050];
    struct point {
        double l;
        double r;
    }p[1050];
    bool cmp(point a, point b)
    {
        if (a.r == b.r)
            return a.l > b.l;
        return a.r < b.r;
    }
    int main(void)
    {
        ios::sync_with_stdio(false);
        int n;
        double d;
        int k = 1;
        while (cin >> n >> d)
        {
            if (n == 0 && d == 0) break;
            int flag = 0;
            for (int i = 0; i < n; i++)//n是海洋中小岛的数目,d是大炮可以覆盖的距离
            {
                cin >> island[i].x >> island[i].y;
                if (island[i].y > d || island[i].y < 0)
                    flag = 1;
                else
                {
                    p[i].l = double(island[i].x - sqrt(d * d - island[i].y * island[i].y));
                    p[i].r = double(island[i].x + sqrt(d * d - island[i].y * island[i].y));
                }
            }
            if (flag == 1)
            {
                cout << "Case " << k << ": " << "-1" << endl;
                k++;
            }
            else
            {
                sort(p, p + n, cmp);
                double r = p[0].r;
                int count = 1;
                for (int i = 1; i < n; i++)
                {
                    if (p[i].l <= r)
                        continue;
                    else
                    {
                        count++;
                        r = p[i].r;
                    }
                }
                cout << "Case " << k << ": " << count << endl;
                k++;
            }
        }
        return 0;
    }
  • 相关阅读:
    ubuntu frp 自编译。本文不能按顺序来 请自己理解
    油猴子 自改脚本 删除页面 div 上下翻页 视频页内全屏 右键可用
    批处理bat 删除指定文件夹下的文件及文件夹
    LUA 静态库 动态库 LD_LIBRARY_PATH 动态库的查找路径 GCC “-l”参数
    delphi 判断奇数偶数
    sf.net
    cmake指定mingw编译器的方法
    关闭delphi ide皮肤
    arch pacman被删除 重装
    delphi 匿名方法访问var参数
  • 原文地址:https://www.cnblogs.com/ZJNU-huyh/p/13208115.html
Copyright © 2011-2022 走看看