作者:ltxys | 来源:互联网 | 2024-12-09 13:04
本问题探讨了如何使用最少数量的雷达站来覆盖海上的所有岛屿。假设海岸线为一条无限长的直线,陆地位于一侧,海洋位于另一侧。每个岛屿视为海洋一侧的一个点,而雷达站则建立在海岸线上,其覆盖范围为固定距离d。
雷达覆盖问题
时间限制:1000 ms | 内存限制:65535 KB难度:3
- 问题描述
设海岸线为一条无限长的直线,陆地在海岸线的一侧,海洋在另一侧。每个岛屿被视为海洋一侧的一个点。雷达站只能建立在海岸线上,且每个雷达站的覆盖范围为d。给定每个岛屿的位置坐标和雷达站的覆盖范围,编写程序计算覆盖所有岛屿所需的最少雷达站数量。注意,岛屿的位置由其x-y坐标表示。
- 输入格式
输入包含多个测试用例。每个测试用例的第一行包含两个整数n (1≤n≤1000) 和d,分别表示海上的岛屿数量和雷达站的覆盖范围。接下来n行每行包含两个整数,表示每个岛屿的位置坐标。每个测试用例之间以空行分隔。输入以一行包含两个零结束。
- 输出格式
对于每个测试用例,输出一行包含测试用例编号和所需的最少雷达站数量。若无法覆盖所有岛屿,则输出-1。
- 样例输入
3 2
1 2
-3 1
2 1
1 2
0 2
0 0
- 样例输出
Case 1: 2
Case 2: 1
解决策略:
采用贪心算法,首先根据岛屿位置计算出每个岛屿对应的雷达站可能的最左和最右安装位置。然后对这些位置进行排序,优先选择能够覆盖更多岛屿的位置。具体步骤如下:
1. 计算每个岛屿对应的雷达站可能的最左和最右安装位置。
2. 按照最右安装位置从小到大排序,如果最右安装位置相同,则按最左安装位置从大到小排序。
3. 遍历排序后的列表,每次选择当前未覆盖岛屿中能够覆盖最远距离的雷达站位置。
4. 重复上述过程直到所有岛屿都被覆盖或确定无法覆盖所有岛屿。
证明:
为了确保算法的有效性,需要证明这种贪心策略总是能得到最优解。通过分析可以发现,每次选择最右端点能够最大化当前雷达站的覆盖范围,从而减少所需雷达站的数量。
#include
#include
#include
#include
using namespace std;
const int maxn = 1010;
struct Interval {
double left, right;
} intervals[maxn];
bool compare(Interval a, Interval b) {
if (a.right return true;
else if (a.right == b.right) {
if (a.left > b.left)
return true;
return false;
}
return false;
}
int main() {
double x, y;
int n, d;
int case_num = 1;
while (cin >> n >> d && (n || d)) {
bool feasible = true;
for (int i = 1; i <= n; i++) {
cin >> x >> y;
double temp = d * d - y * y;
if (temp <0 || d <0)
feasible = false;
else if (feasible) {
intervals[i].left = x - sqrt(temp);
intervals[i].right = x + sqrt(temp);
}
}
if (!feasible) {
cout <<"Case " < continue;
}
sort(intervals + 1, intervals + 1 + n, compare);
int count = 1;
double current_right = intervals[1].right;
for (int i = 2; i <= n; i++) {
if (current_right count++;
current_right = intervals[i].right;
}
}
cout <<"Case " < }
return 0;
}