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 ", flag ? result : -1); } return 0; }