原题地址
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)
来源:https://www.cnblogs.com/lecholin/p/6705266.html