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
思路:
贪心思想,将问题转化为区间覆盖问题,将草地的上边界作为要覆盖的区间,计算出每个洒水器覆盖的区间范围,不能覆盖的舍去,然后将洒水器按覆盖范围的左边界升序排列。
要覆盖的最右边的点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

该博客讨论了如何应用贪心算法解决UVa 10382问题,即在覆盖一定长度草地的区间覆盖问题。通过将问题转化为区间覆盖,舍去无法覆盖的洒水器,并按覆盖范围升序排列,逐步找到能覆盖最远区域的洒水器,以求得覆盖整个草地所需的最小洒水器数量。如果无法覆盖所有草地,则输出-1。
1966

被折叠的 条评论
为什么被折叠?



