POJ 1238 Radar Installation(贪心)

Description

Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d.

We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates.

Figure A Sample Input of Radar Installations
在这里插入图片描述

Input

The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases.

The input is terminated by a line containing pair of zeros

Output

For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. “-1” installation means no solution for that case.

Sample Input

3 2
1 2
-3 1
2 1

1 2
0 2

0 0

Sample Output

Case 1: 2
Case 2: 1

思路

雷达的搜索距离有范围d,那么可以收到某一个岛的全部雷达都在以到为圆心以d为半径的圆内。雷达都在都x轴上,那么雷达的范围就可以确定了,在圆与x轴的两个交点之间。也就是说,只有雷达在这个区间才可以搜索到该岛。将每一个岛存储为一个区间,问题就转换为了,求最少数的点,使所有区间内均有点。区间在读入数据时,用勾股定理即可求出。将所有区间按照左端点从小到大排序
在这里插入图片描述
如图,假设4条线段为4个区间,第二条线段的左端点小于第一条线段的右端点,那么将雷达放在第二条线段的左端点,可以覆盖第一个岛和第二个岛。第三条线段的左端点小于第二条线段的右端点,雷达放在第三条线段的左端点也可以。第四条线段的左端点大于第三条线段的右端点,放在第四条线段的左端点,不可以覆盖第三个岛,不行,所以雷达只能放在第三区间左端点。至于为什么都要放在左端点,因为如果放在左端点右面的,左端点前面可以到达的位置,左端点右面的点不都可以到达。当然放在右面的点可以在右面到达更大的范围,可能覆盖到后面的区间,但我们只考虑判断的区间前面的区间,后面的区间后面判断。也可以用右端点,那么排序时就要按照右端点来排序。
按照上面的方式遍历每一个区间,如果安置了一个雷达,更新雷达的位置,判断当前的区间和上一个雷达之间的区间是否覆盖。
最后答案需要加1,因为每次判断都是安装到前面的某个区间,这个区间的右端点大于正在判断的区间的左端点,那么将雷达安装在这个前面的某个区间的左端点,肯定没有在正在判断这个区间的范围内。所有最后另需一个雷达来覆盖最后一个岛。
注意,判断不成立的情况。读入数据时判断即可,如果岛的纵坐标的绝对值大于雷达的距离,则不成立。但此时不能退出循环,需要将所有的数据读完。还需注意,题中说点是整数,但数据不全是,用double存储。

代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;

struct node
{
    
    
	double l,r;								//区间 
}w[1005];

bool cmp(const node a,const node b)
{
    
    		
	return a.l<b.l;							//排序从小到大 
}

int main()
{
    
    
	int cnt=0,n;
	int d;
	while(1)
	{
    
    
		cnt++;
		cin>>n>>d;
		if(n==0)
			return 0;
		bool flag=0;
		for(int i=1;i<=n;i++)
		{
    
    
			int a,b;
			scanf("%d%d",&a,&b);
			if(flag)
				continue;
			if(fabs(double(b))>d)			//判断是否有可能 
			{
    
    
				flag=1;						//标记 
				continue;					//继续读入数据 
			}
			double tmp=(d*d-b*b);			//勾股定理 
			w[i].l=a-sqrt(tmp);				//区间 
			w[i].r=a+(tmp);
		}
		if(flag)
		{
    
    
			cout<<"Case "<<cnt<<": "<<"-1"<<endl;
			continue;
		}
		sort(w+1,w+n+1,cmp);				//排序 
		int pos=0,ans=0;					//初始 雷达的位置为0,数量为0  
		for(int i=1;i<=n;i++)
		{
    
    
			for(int j=pos+1;j<i;j++)		//上一个雷达的位置加1 
			{
    
    
				if(w[i].l>w[j].r)			//左端点>大于某个区间的右端点 
				{
    
    
					ans++;					//雷达需要放在上一个区间的左端点 
					pos=i-1;
					break;
				}
			}
		}									//最后答案需要加1
		cout<<"Case "<<cnt<<": "<<ans+1<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/m0_54621932/article/details/113923602