POJ1328_Radar Installation_贪心

Radar Installation
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 84620 Accepted: 18898

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

/*******************************************
这么一个题居然做了俩小时,心疼自己的青春。。

一开始思路错了
错误思路:从左到右枚举点。如果点被包含在已有
的区域内,则不管。如果没有被包含,则需要增加
一个雷达。这个雷达在包含这个点的前提下尽可能
的靠右。因为有y的限制,所以这个贪心思路是不
对的(如果不用考虑y而但考虑x的话,这样是没
问题的。可这样就水的不像样子了)。

wa炸了就跑去看dicuss,测了几组数据才发现原来
思路错了。
然后不小心看到了大佬的思路(感觉这思路自己完
全能想到)。于是按照对的思路又开始写。

沿着正确思路写的时候,脑子里忽然冒出来很多奇
技淫巧,像什么求前缀和呀,栈啊之类的。想到一
出是一出,写完了测数据发现不对,又推了重写。

所以以后还是把思路想明白了再动手写,省得浪费
时间。
还有,如果是比赛的时候,效率差不多的情况下还
是选择更朴素的、更熟悉的方法比较靠谱。

就这么两个小时过去了。。。万幸今天晚上还能把
它写对。下面上具体方法。

*********************************************

首先以每个点为圆心,d为半径画圆,交x轴于两点
l, r。

如果交不上,那就说明出现了 y>d 或 d=0 的情况,
初次之外不合法的情况还有 y<0 和 d<0。对于不
合法的情况,直接输出-1就可以了。

每一对l,r形成了一个区间。每一个区间内都至少
要有一个雷达。

将各区间按 l 从小到大进行排序,然后逐个枚举。

如果后面一个区间的 l 小于等于当前区间的 r,说
明这两个区间有交集,只要在这个交集内安一个雷
达就能覆盖这两个岛了。

先别急这放雷达,万一能用一个雷达覆盖更多的岛
呢。所以,这时要做的时更新 e,e就是当前区间
的右端点,它的值为当前区间内所有 l,r 区域的
r的最小值。也就是e=min(e,r)。

如果后面一个区间的 l 大于当前区间的 r ,说明
这两个区间没有交集,那就在前一个区间的交集上
放一个雷达,然后 e=r。

这里需要注意的一点是,我们每次都是把相交的区
间都处理完了才给放雷达,也就是始终都是欠着一
个雷达的。所以输出结果时要加上1。
*******************************************/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>

using namespace std;

typedef pair<double, double> P;
P land [1010];

P f (int x, int y, int d)
{
	P ans;
	ans.first = x - sqrt(1.0*d*d - 1.0*y*y);
	ans.second = x + sqrt(1.0*d*d - 1.0*y*y);
	return ans;
}

int main ()
{
	int n, d, cas = 0;
	while(1){
		bool flag = 0;

		scanf("%d %d", &n, &d);
		if( n == 0 && d == 0 ) return 0;

		for(int i= 0; i< n; i++){
			int x, y;
			scanf("%d %d", &x, &y);
			if( d <= 0 || y < 0 || y > d ) flag = 1;
			land[i] = f(x, y, d);
		}

		if( flag ){
			printf("Case %d: -1\n", ++cas);
			continue;
		}

		sort(land, land+n);

		int cnt = 0;
		double e = land[0].second;
		for(int i= 1; i< n; i++){
			if(land[i].first <= e) e = min(e, land[i].second);
			else cnt ++, e = land[i].second;
		}

		printf("Case %d: %d\n", ++cas, cnt+1);
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值