UVa 10382 - Watering Grass(贪心算法,区间覆盖问题)

Problem E
Watering Grass
Input:
standard input
Output: standard output
Time Limit: 3 seconds

n sprinklers are installed in a horizontal strip of grass l meters long andw meters wide. Each sprinkler is installed at the horizontal center line of the strip. For each sprinkler we are given its position as the distance from the left end of the center line and its radius of operation.

What is the minimum number of sprinklers to turn on in order to water the entire strip of grass?

Input

Input consists of a number of cases. The first line for each case contains integer numbersn, l and w with n <= 10000. The next n lines contain two integers giving the position of a sprinkler and its radius of operation. (The picture above illustrates the first case from the sample input.)

 

Output

For each test case output the minimum number of sprinklers needed to water the entire strip of grass. If it is impossible to water the entire strip output -1.

Sample input

8 20 2

5 3

4 1

1 2

7 2

10 2

13 3

16 2

19 4

3 10 1

3 5

9 3

6 1

3 10 1

5 3

1 1

9 1

 

Sample Output

6

2

-1

(Regionals 2002 Warm-up Contest, Problem setter: Piotr Rudnicku)

 

思路:

贪心思想,将问题转化为区间覆盖问题,将草地的上边界作为要覆盖的区间,计算出每个洒水器覆盖的区间范围,不能覆盖的舍去,然后将洒水器按覆盖范围的左边界升序排列。

要覆盖的最右边的点rightmost的初始值为0,遍历洒水器,找一个能覆盖住rightmost且覆盖范围的右边界最大的洒水器,然后将该洒水器覆盖的右边界作为新的rightmost,重复刚才的过程,直到覆盖整个草地。

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

#define MAX_SIZE 10000

struct Sprinkler
{
	double left;
	double right;
	bool operator < (const Sprinkler &s) const
	{
		return left < s.left;
	}
}sprinklers[MAX_SIZE+5];

int WaterTheGrass(int m, int l)
{
	double rightmost = 0.0;
	int count = 0;
	int i, j;
	for (i = 0; i < m; i = j)
	{
		if (sprinklers[i].left > rightmost) break;
		for (j = i+1; j < m && sprinklers[j].left <= rightmost; ++j)
		{
			if (sprinklers[j].right > sprinklers[i].right)
			{
				i = j;
			}
		}
		++count;
		rightmost = sprinklers[i].right;
		if (rightmost >= l) break;
	}
	if (rightmost >= l)
	{
		return count;
	}
	return -1;
}

int main(void)
{
	int n, l;
	double w;
	while (cin >> n >> l >> w)
	{
		w /= 2.0;
		int i, m = 0;
		for (i = 0; i < n; ++i)
		{
			int p, r;
			scanf("%d%d", &p, &r);
			if (r > w)
			{
				double halfCoveredLen = sqrt((double)r*r - w*w);	//注意转化为double型,错了好几次...
				sprinklers[m].left = (double)p - halfCoveredLen;
				sprinklers[m++].right = (double)p + halfCoveredLen;
			}
		}
		sort(sprinklers, sprinklers+m);
		cout << WaterTheGrass(m, l) << endl;
	}
	return 0;
}
欢迎转载,请尊重作者,转载请标明出处: http://blog.csdn.net/code_pang/article/details/17919533

你可能感兴趣的:(贪心算法,区间覆盖)