【C++】「一本通 1.1 例 3」喷水装置(Watering Grass)

【来源】

一本通题库-1424
UVA-10382
LibreOJ-10002
Kattis-grass
vjudge

各题库题目意思相同,但输入格式、数据范围略有不同。

【题目描述】

L L 米,宽 W W 米的草坪里装有 n n 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 W 2 \frac{W}{2} 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。
在这里插入图片描述

请问:如果要同时浇灌整块草坪,最少需要打开多少个喷头?

【输入格式】

输入包含若干组测试数据。

第一行一个整数 T T 表示数据组数;

每组数据的第一行是整数 n L n、L W W

接下来的 n 行,每行包含两个整数,给出一个喷头的位置和浇灌半径(上面的示意图是样例输入第一组数据所描述的情况)。

【输出格式】

对每组测试数据输出一个数字,表示要浇灌整块草坪所需喷头数目的最小值。如果所有喷头都打开也不能浇灌整块草坪,则输出 1 −1

【输入样例】

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。

【解析】

贪心。

将喷头喷水的有效范围求出来并过滤掉喷水直径小于草坪宽的喷头。

然后可以将问题转化为区间完全覆盖问题,等价于给定一个长度为 m m 的区间,再给出 n n 条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖。

将每一个区间按照左端点递增顺序排列,这里贪心的策略是每次在可选线段里选取右端点最大的,直至完全覆盖。

【代码】

一本通/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;
}
发布了106 篇原创文章 · 获赞 156 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/Ljnoit/article/details/105342029
今日推荐