【来源】
一本通题库-1424
UVA-10382
LibreOJ-10002
Kattis-grass
vjudge
各题库题目意思相同,但输入格式、数据范围略有不同。
【题目描述】
长
米,宽
米的草坪里装有
个浇灌喷头。每个喷头都装在草坪中心线上(离两边各
米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。
请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?
【输入格式】
输入包含若干组测试数据。
第一行一个整数 表示数据组数;
每组数据的第一行是整数 和 ;
接下来的 n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。
【输出格式】
对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 。
【输入样例】
3
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
【输出样例】
6
2
-1
【数据范围】
对于 100% 的数据,n≤15000。
【解析】
贪心。
将喷头喷水的有效范围求出来并过滤掉喷水直径小于草坪宽的喷头。
然后可以将问题转化为区间完全覆盖问题,等价于给定一个长度为 的区间,再给出 条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖。
将每一个区间按照左端点递增顺序排列,这里贪心的策略是每次在可选线段里选取右端点最大的,直至完全覆盖。
【代码】
一本通/LibreOJ:
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=15005;
struct Node {
double l,r;
bool operator < (const Node &rhs) const {
return l<rhs.l;
}
} a[N];
int main() {
int T;
scanf("%d",&T);
while(T--) {
int n,L,W;
scanf("%d%d%d",&n,&L,&W);
int cnt=0;
for(int i=1; i<=n; i++) {
int x,r;
scanf("%d%d",&x,&r);
if(r<W/2.0) continue;
double tmp=sqrt(r*r-W*W/4.0);
a[++cnt].l=1.0*x-tmp;
a[cnt].r=1.0*x+tmp;
}
sort(a+1,a+cnt+1);
double t=0;
int ans=0,i=1,flag=0;
while(t<L) {
ans++;
double s=t;
while(a[i].l<=s && i<=cnt) {
if(t<a[i].r) t=a[i].r;
i++;
}
if(t==s && s<L) {
printf("-1\n");
flag=1;
break;
}
}
if(!flag) printf("%d\n",ans);
}
return 0;
}
UVA/Kattis:
//注意:UVA中输入的变量类型要用浮点数的
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=1e4+5;
struct Node {
double l,r;
bool operator < (const Node &rhs) const {
return l<rhs.l;
}
} a[N];
int main() {
int n,L;
double W;
while(~scanf("%d%d%lf",&n,&L,&W)) {
int cnt=0;
for(int i=1; i<=n; i++) {
double x,r;
scanf("%lf%lf",&x,&r);
if(r<W/2) continue;
double tmp=sqrt(r*r-W*W/4);
a[++cnt].l=x-tmp;
a[cnt].r=x+tmp;
}
sort(a+1,a+cnt+1);
double t=0;
int ans=0,i=1,flag=0;
while(t<L) {
ans++;
double s=t;
while(a[i].l<=s && i<=cnt) {
if(t<a[i].r) t=a[i].r;
i++;
}
if(t==s && s<L) {
printf("-1\n");
flag=1;
break;
}
}
if(!flag) printf("%d\n",ans);
}
return 0;
}