poj1328
解题思路:
逆向思维:将雷达所能覆盖的区域转换为岛屿能被覆盖是时,对应x轴雷达可处的线段。既以岛屿为
圆心,雷达可勘测距离为半径,求x轴相交的线段。
(1)首先我们求出在每个岛屿放雷达以后在x轴上所能覆盖的区间,是在x轴的上的一个线段,即在这
一段上放置雷达可以覆盖到该岛。
(2)我们把每个岛对应的线段找出来,只要在这些线段上放置一些雷达,使得所有的线段上都有雷达
即可符合题意(注意如果半径为0或者坐标的y轴小于半径的话将无法完成覆盖,输出-1)。
(3)我们将线段根据左端点排序,找出如果一个线段包含另一个线段,则可以忽略外面的那一个线段
(道理很简单),将其设为无效。
(4)在剩下的线段中从左往右遍历,对于每个线段,尽量选取该线段的最右边的点作为雷达,如果之
前有雷达在该线段上,则跳过该线段。
(5)每次加一个雷达将计数器加一,最后可以得到解。
代码:
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
using namespace std;
//采用逆向思维,贪心策略
//某个岛屿可被雷达探测到的对应雷达所处的位于x轴的区域
typedef struct point
{
double left;
double right;
}point;
point arr[1000];
bool cmp( point&a, point&b)
{
return a.left < b.left;//贪心,通过岛屿的位置确定雷达所处的范围
}
int main()
{
int d, n;//d:雷达可探测举例,n:岛屿个数
int kase = 0;
while (cin >> n >> d)
{
if (n == 0 && d == 0)
break;
bool flag = false;//判断是否为无法覆盖的点
double x, y;//岛屿的坐标
for (int i = 0; i < n; i++)
{
cin >> x >> y;
//判断岛屿是否无法被覆盖
if (y > d)
{
flag = true;//true标记无法覆盖的点
}
//求此时岛屿对应的x轴雷达安置范围
arr[i].left = x - sqrt(d * d - y * y);
arr[i].right = x + sqrt(d * d - y * y);
}
if (flag ==true)//存在无法覆盖的点
{
cout << "Case " << ++kase << ": -1" << endl;
continue;
}
sort(arr, arr + n, cmp);//将arr数组按照cmp方式进行排序
double right = arr[0].right;
int ans = 1;//统计雷达数目
for (int i = 1;i < n; i++)
{
if (arr[i].left <=right)
right = min(right, arr[i].right);//更新
else
{
right = arr[i].right;
ans++;
}
}
cout << "Case " << ++kase << ": " << ans << endl;
}
}

浙公网安备 33010602011771号