描述
假设滑行是无限直线。土地位于海岸的一侧,海洋位于另一侧。每个小岛都位于海边。并且位于滑行的任何雷达装置只能覆盖d距离,因此如果它们之间的距离最多为d,则可以通过半径装置覆盖海中的岛屿。
我们使用笛卡尔坐标系,定义滑行是x轴。海侧在x轴上方,陆侧在下方。考虑到每个岛屿在海中的位置,并考虑到雷达装置覆盖范围的距离,您的任务是编写一个程序,以找到覆盖所有岛屿的最小数量的雷达装置。注意,岛的位置由其xy坐标表示。
这个题最开始是想以雷达为圆心来判断圆内的点,发现不知道如何判断几个点是否在一个圆内,而且不知道雷达的坐标,后来换思路(网上借鉴),要以点为中心,跟x轴相交于两点,在这条线上的雷达都可以包含这个点,要得到雷达最小,就要使得线段重合得最多,问题变成了贪心+区间线段问题。
- #include <iostream>
- #include <math.h>
- #include <algorithm>
- using namespace std;
- const int MAXN = 1010;
- int T, n, d;
- struct node
- {
- double left, right;
- }a[MAXN];
- bool operator < (const node &a, const node &b)
- {
- return a.left < b.left;
- }
- int solve()
- {
- int ans;
- double now;
- sort(a, a + n);
- ans = 1;
- now = a[0].right;
- for (int i = 1; i < n; ++i)
- {
- if (a[i].left <= now)
- {
- now = min(a[i].right, now);
- }
- else
- {
- ++ans;
- now = a[i].right;
- }
- }
- return ans;
- }
- int main()
- {
- int x, y;
- int flag;
- T = 0;
- while (1)
- {
- ++T;
- flag = 1;
- cin >> n >> d;
- if (n == 0 && d == 0)break;
- for (int i = 0; i < n; ++i)
- {
- cin >> x >> y;
- if (y > d)
- {
- flag = 0;
- break;
- }
- else
- {
- if (y == d)
- {
- a[i].left = a[i].right = x;
- }
- else
- {
- a[i].left = x - sqrt(d*d - y * y);
- a[i].right = x + sqrt(d*d - y * y);
- }
- }
- }
- if (flag)
- {
- cout << "Case " << T << ": " << solve() << endl;
- }
- else
- {
- cout << "Case " << T << ": -1" << endl;
- }
- }
- return 0;
- }