POJ 3069 Saruman's Army(贪心+区间覆盖)

原题地址

http://poj.org/problem?id=3069

题意:X轴上有n个点Xi,雷达必须被放置在点上,且能探测与其距离为R内的所有点,求能覆盖所有点的最少雷达数。

解题思路

这题属于贪心算法的题目,很明显也是区间覆盖问题。

我也是愚蠢到极致了,才会想着记录每个点的R范围内的邻居数,对邻居数降序排,在邻居数最多的点上放雷达。浪费了一个半小时,数组套数组,还是WA,debug失败只能参考大神的博客。

看了大神的解释,醒悟到这题与上一篇POJ 2586应该是同一种思路,即让特殊点的影响尽量向后面辐射,来减少之后摆放标记点的数目。

贴一下大神的博客:POJ3069 POJ2586 解题报告(异曲同工的贪心算法)

总结一下外层while循环里执行的任务:

  • 从左到右看,选择需要被新雷达覆盖的最左点xi
  • 找到[xi, xi+R]内最靠右的点,放置新的雷达
  • 找到新雷达Xj辐射范围[xj, xj+R]内的最靠右的点,其下一个点就是下一个雷达要覆盖的最左点

AC代码

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

int main()
{
    int a[1001];
    int R,n;
    while (cin >> R >> n)
    {
        if (R == -1 && n == -1) break;
        for (int i = 0; i<n; ++i)
            cin >> a[i];
        sort(a, a+n); //按横坐标升序
        int index = 0, cnt = 0;
        while (index < n) //判断时index指向旧雷达探测不到的最左点
        {
            //找到当前点右侧R范围内最靠右的点,即雷达摆放点
            int range = a[index] + R;
            while (index < n && a[index] <= range)
                index++; //跳出时index指向雷达摆放点的下一个

            cnt++; //在index-1位置放新雷达

            //跳出新雷达的右界,即找到下一个雷达探测的最左点
            range = a[index-1]+R; //以index-1为圆心的右侧R范围
            while (index < n && a[index] <= range)
                index++;
        }
        cout << cnt << endl;
    }
    return 0;
}

内存占用: 232K 耗时:63ms
算法复杂度:O(n2

posted @ 2017-04-07 21:00  Lecholin  阅读(94)  评论(0编辑  收藏  举报