UVa-10382 Watering Grass (区间覆盖贪心)

题目链接

题意:

有一块草坪,长为l,宽为w,在它的水平中心线上可安置n个喷水头,每个喷水头可以覆盖半径为r的圆,求最少用多少个喷水头覆盖整个草坪

思路:

只有喷水半径大于草坪宽度的喷水头才有可能被计算,每个喷水头的有效覆盖都是宽度等于草坪宽度,长度为$r^2-\frac{w^2}{4.0}$的矩形,从而得到矩形左边和右边的坐标,把问题转化为区间覆盖问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <cmath>
#include <set>
#include <queue>
#include <map>
#include <algorithm>
#define ROP freopen("D:\\input.txt", "r", stdin);
const int INF=0x3f3f3f3f;
typedef long long ll;
int dir[][2]= {1,0,-1,0,0,1,0,-1};
const int MAXN=1e5+5;
using namespace std;
struct rec
{
double l,r;
friend bool operator<(const rec& r1,const rec& r2)
{
return r1.l<r2.l;
}
}a[MAXN];
int main()
{
//ROP;
int t;
ll l,w;
ll r,s;
while(~scanf("%d%lld%lld",&t,&l,&w))
{
int cnt=0,ans=0;
double pos=0;
for(int i=0; i<t; i++)
{
scanf("%lld%lld",&s,&r);
if(2*r>w)
{
double del=sqrt(r*r-w*w/4.0);
a[cnt].l=s-del>0?s-del:0;
a[cnt].r=s+del<l?s+del:l;
cnt++;
}
}
sort(a,a+cnt);
int k=-1;
while(pos<l&&a[k+1].l<=pos)
{
double maxn=-1;
for(int i=k+1;a[i].l<=pos&&i<cnt;i++)
if(a[i].r>maxn)
{
maxn=a[i].r;
k=i;
}
pos=maxn;
ans++;
}
if(pos<l)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}

之前wa了很多次,被数据范围坑了= =