E - 贪心-- 区间覆盖

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=85904#problem/E

解题思路:

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

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

程序代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAX 10005

struct node
{
 double left, right;
 bool operator <(const node &a) const
 {
  return left < a.left;
 }
}p[MAX];

int n, num;
double l, w;

int main()
{
 int i;
// freopen("input.txt", "r", stdin);
 while(scanf("%d %lf %lf", &n, &l, &w) != EOF)
 {
  num = 0;
  double po, r;
  for(i = 0; i < n; ++i)
  {
   scanf("%lf %lf", &po, &r);
   if(r <= w/2) continue;
   double t = sqrt(r*r-w*w/4.0);
   p[num].left = po-t;
   p[num++].right = po+t;
  }

  sort(p, p+num);
  double left = 0, right = 0;
  bool flag = false;
  int result = 0;
  i = 0;
  if(p[0].left <= left)
  {
   while(i < num)
   {
    int j = i;
    while(j < num && left >= p[j].left)
    {
     if(p[j].right > right)
      right = p[j].right;
     ++j;
    }
    if(j == i) break;
    result++;
    left = right;
    i = j;
    if(left >= l)
    {
     flag = true;
     break;
    }
   }
  }

  printf("%d\n", flag ? result : -1);
 }
 return 0;
}
View Code