区域覆盖问题

POJ1328是一道经典的贪心算法例题。题目大意是假设海岸线是一条无限延伸的直线。陆地在海岸线的一侧,而海洋在另一侧。每一个小的岛屿是海洋上的一个点。雷达
坐落于海岸线上,只能覆盖d距离,所以如果小岛能够被覆盖到的话,它们之间的距离最多为d。题目要求计算出能够覆盖给出的所有岛屿的最少雷达数目。对于每个小岛
,我们可以计算出一个雷达所在位置的区间。问题转化为如何用尽可能少的点覆盖这些区间。先将所有区间按照左端点大小排序,初始时需要一个点。如果两个区间相交而不重合,我们什么都不需要做;如果一个区间完全包含于另外一个区间,我们需要更新区间的右端点;如果两个区间不相交,我们需要增加点并更新右端点。




贪心具体思路:


图中ABCD为海岛的位置。假设本题半径为2(符合坐标系),那么A点坐标为(1,1)以此类推。

首先以A为圆心,r为半径做圆,交x轴与E1(右)点,做出如图中绿色虚线圆。然后以E1为圆心,半径为r做圆。看此时下一点(B)是否在该圆中。

存储图中红色圆与X轴的交点。先排序,但排序的准则是按红色圆与x轴左交点的先后顺序。

如图,如果B点圆(且如此称呼)的左交点(J1点)在A点圆右交点(E1)左侧,那么B点一定涵盖在A点圆内部。再如图,如果D点圆的左交点(图中未标示)在A点圆的右交点(未标示)右,则D点不在A点圆中。


题目要求

输入
输入由几个测试用例组成。每个案例的第一行包含两个整数n(1 <= n <= 1000)和d
,其中n是海中的岛屿数,d是雷达装置的覆盖距离。其后是n行,每行包含表示每个岛
的位置坐标的两个整数。接下来是一个空白行,以分开案例。
输入端由包含零对的行终止

输出:
对于每个测试用例,输出一行包括测试用例编号,然后是所需的最少数量的雷达安装。
“-1”安装意味着没有解决办法。
样品输入
3 2
1 2
-3 1
2 1


1 2
0 2


0 0  //退出
样品输出
情况1:2
情况2:1

代码及注释:(注释较多)可帮助理解

#include 
#include 
#include 
using namespace std;


struct Between
{
	double left;
	double right;
}between[1001];

bool cmp( Between a,  Between b)
{
	return a.left < b.left;//由小到大排序
}

int main()
{
	int n, d;//n表示n个小岛 d表示雷达探测半径 
	int sw;//sw作为边界的判断。如果小岛到海岸的距离大于雷达的探测距离,则雷达不可能检测到小岛
	int re, count = 1;//count 代表第几个例子
	int x, y;//x,y 代表的是小岛的坐标
	double pre;//先前的点
	//雷达可以设置在河岸区间的任何一个地方。这样都能探测到当前的小岛
	//若雷达设置在起始岛的右边界的话,就能保证留给后续岛的覆盖空间是最大的。
	while (1)
	{
		cin >> n >>d;
		if (n == 0 && d == 0)break;//输入 0 0 时退出程序
		
		sw = 1;//设置检测条件
		for (int i =0;i> x >> y;
			if (d >= y&&sw == 1) //小岛到岸边的距离为y。雷达探测距离d需要大于y
			{
				between[i].left = x - sqrt((double)d*d - (double)y*y);
				between[i].right = x + sqrt((double)d*d - (double)y*y);
			}
			else
			{
				sw = 0;
			}
		}
		if (sw == 0)
		{
			cout << "Case" << count++ << " : " << -1 << endl;//若该小岛不能探测到的话,返回-1.
			continue;
		}

		sort(between, between + n, cmp);//按照到岸边的左边界由小到大进行排列
		re = 1;//设置雷达的个数
		pre = between[0].right;//第一个岛的右边界
		for (int i = 1; i < n; i++)
		{
			if (between[i].left > pre)//如果其它小岛的左边界大于现在岛的右边界,则雷达不能同时
						 //覆盖这两个岛。需要增加雷达个数
			{
				re++;
				pre = between[i].right;//并且,当前的边界换成新岛的右界
			}
			else
			{
				if (between[i].right


 

你可能感兴趣的:(区域覆盖问题)