一本通网站 1424:【例题3】喷水装置 及 贪心总结

原题   传送门

【题目描述】

长 LL 米,宽 WW 米的草坪里装有 nn 个浇灌喷头。每个喷头都装在草坪中心线上(离两边各 W2W2 米)。我们知道每个喷头的位置(离草坪中心线左端的距离),以及它能覆盖到的浇灌范围。

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

【输入】

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

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

每组数据的第一行是整数 nn、LL 和 WW;

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

【输出】

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

对于这个题,首先我们要考虑到装置实际覆盖的范围:

由于曲线不好处理,所以我们可以将覆盖面积近似的看成是图中红色矩形覆盖的面积(这样对结果不造成影响)

那么这个矩阵的左端点与大区间最左侧的距离为 pos-√[r^2+(w/2)^2],矩形的右端点与大区间最左侧的距离为pos+√[r^2+(w/2)^2];

接下来是贪心思路:

1.在读入每个喷水装置的数据后,我们紧接着计算出实际矩形的左端点和右端点的距离l和r,记录在结构体中;

2.根据矩形左端点从大到小排序;

3.我们设double类型的s来表示已经覆盖区间的范围,初始值为0;

4.我们先用q来暂时储存一下s每次操作前的值,然后访问每一个l<=s且在cnt内的点,找出最大的r,让s=r(此时这个r是最大的那个r);

判无解:若q==s且s<l,则说明无解(意思就是没能找到一个装置来更新s,并且s还未覆盖整个区间)

好啦,代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int read()                      //读入优化
{
    char ch=getchar();
    int a=0,x=1;
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘) x=-x;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘)
    {
        a=(a<<3)+(a<<1)+(ch-‘0‘);
        ch=getchar();
    }
    return a*x;
}
int t,n,l,w;
int pos,R,ans,cnt;
struct water
{
    double l,r;                 //l是装置实际覆盖区间的左端点,r是右端点
}a[15001];
int cmp(water x,water y)        //按照左端点从大到小排序
{
    return x.l<y.l;
}
int main()
{
    t=read();                   //t组数据
    for(int i=1;i<=t;i++)
    {
        n=read();
        l=read();
        w=read();
        cnt=0;                  //cnt是有用的装置的个数,条件为r>w/2
        for(int j=1;j<=n;j++)
        {
            pos=read();         //装置圆心距区间最左端的距离
            R=read();
            if(R<=w/2) continue;
            cnt++;
            a[cnt].l=pos-sqrt(R*R-(w/2.0)*(w/2.0));
            a[cnt].r=pos+sqrt(R*R-(w/2.0)*(w/2.0));
        }
        sort(a+1,a+1+cnt,cmp);
        double s=0,q;           //我们已经将区间覆盖了s米
        int k=1,flag=0,ans=0;
        while(s<l)                       //覆盖不满就一直找喷水装置
        {
            ans++;
            q=s;
            for(;a[k].l<=q&&k<=cnt;k++)    //在s左端找到一个右端点最大的值
               if(a[k].r>s) s=a[k].r;      //让s更新为最大的r
            if(s==q&&s<l) {flag=1;cout<<0<<endl;break;}  //判断无解
        }
        if(flag==0) cout<<ans<<endl;
    }
    return 0;
}

在此对贪心做一下小结:

贪心算法是指:

在每一步求解的步骤中,它要求“贪婪”的选择最佳操作,并希望通过一系列的最优选择,能够产生一个问题的(全局的)最优解。

  贪心算法每一步必须满足一下条件:

  1、可行的:即它必须满足问题的约束。

  2、局部最优:他是当前步骤中所有可行选择中最佳的局部选择。

  3、不可取消:即选择一旦做出,在算法的后面步骤就不可改变了。

贪婪算法并没有固定的算法解决框架,算法的关键是贪婪策略的选择,根据不同的问题选择不同的策略。必须注意的是策略的选择必须具备无后效性,即某个状态的选择不会影响到之前的状态,只与当前状态有关,所以对采用的贪婪的策略一定要仔细分析其是否满足无后效性。

原文地址:https://www.cnblogs.com/xcg123/p/10989095.html

时间: 2024-10-29 10:45:44

一本通网站 1424:【例题3】喷水装置 及 贪心总结的相关文章

一本通网站基础篇完结纪念

一本通网站基础篇题目终于完结,发篇随笔纪念下这一伟大时刻的到来. 一本通网站基础篇题目所有AC代码(点此进入) 说明:此篇所有代码均为网站提交通过的代码且基本都是本人亲写.(当然部分题目也可能参考了网站其他文章.请教了其他老师),如发现代码有错,烦请告知,感谢! 特别明谢:之江学院石老师.江西省丰城中学熊雪芬老师.成都石室中学文老师(也是此网站管理)等给了我很大帮助,还有我的学员督促和鼓励. 友情链接:  (进来了不防帮忙点下上面“我要自学网”图标链接,此链接为我学习网站的推广,换点积分,非常感

一本通网站 1433:【例题1】愤怒的牛

原题 传送门 [题目描述] 农夫 John 建造了一座很长的畜栏,它包括N (2 ≤ N ≤ 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 ≤ xi ≤ 1,000,000,000). 但是,John的C (2 ≤ C ≤ N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗.为了不让牛互相伤害.John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢 [输入] 第一行:空格分隔的两个整数N和C: 第二行---

喷水装置2 贪心

喷水装置(二) 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿.请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿. 输入 第一行输入一个正整数N表示共有n次测试数据.每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度.随后的n行,

一本通网站 1378:最短路径(shopth)

[题目描述] 给出一个有向图G=(V, E),和一个源点v0∈V,请写一个程序输出v0和图G中其它顶点的最短路径.只要所有的有向环权值和都是正的,我们就允许图的边有负值.顶点的标号从1到n(n为图G的顶点数). [输入] 第1行:一个正数n(2≤n≤80),表示图G的顶点总数. 第2行:一个整数,表示源点v0(v0∈V,v0可以是图G中任意一个顶点). 第3至第n+2行,用一个邻接矩阵W给出了这个图. [输出] 共包含n-1行,按照顶点编号从小到大的顺序,每行输出源点v0到一个顶点的最短距离.每

贪心小总结

介绍几种贪心题型 1.选择不相交区间: 按照结束时间从大到小排序,如果区间左端点大于当前最右点就选,否则不选. 例题:活动安排: #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<cmath> #include<queue> using namespace std; const int maxm=1100; int n,

贪心算法-跳跃游戏二

给定一个非负整数数组,假定你的初始位置为数组第一个下标. 数组中的每个元素代表你在那个位置能够跳跃的最大长度. 你的目标是到达最后一个下标,并且使用最少的跳跃次数. 例如: A=[2,3,1,1,4],到达最后一个下标的最少跳跃次数为 2.(先跳跃 1 步,从下标 0 到 1,然后跳跃 3 步,到达最后一个下标.一共两次) 输入格式 第一行输入一个正整数 n(1≤n≤100) ,接下来的一行,输入 n 个整数,表示数组 A. 输出格式 最后输出最少的跳跃次数. 样例输入 5 3 1 1 1 1

到底什么叫贪心策略(内含几个经典贪心样例和三大图论算法)

昨天和前天写完了分治和dp,感觉收获真的挺大的,复习绝不是简单的重复记忆,而是将所学知识融会 贯通的过程,分析各种思想的异同,这些都是在平时学习和刷题的时候没有认真考虑的问题 好了,扯远了 今天分析一下到底什么叫贪心策略 怎么理解贪心:贪心在解决问题上是目光短浅的,仅仅根据当前的已知信息就做出选择,并且一旦做了选择,就不再更改 比如01背包问题,用贪心的话是不可解决的,因为贪心每次只顾眼前最优,即每次选择价值最大的,而忽 略了另外一个变量,物品的重量,如果还考虑物品的重量的话,那就是dp了 贪心

greedy1042

题意解释: John现有h个小时的空闲时间,他打算去钓鱼.钓鱼的地方共有n个湖,所有的湖沿着一条单向路顺序排列(John每在一个湖钓完鱼后,他只能走到下一个湖继续钓),John必须从1号湖开始钓起,但是他可以在任何一个湖结束他此次钓鱼的行程. 此题以5分钟作为单位时间,John在每个湖中每5分钟钓的鱼数随时间的增长而线性递减.每个湖中头5分钟可以钓到的鱼数用fi表示,每个湖中相邻5分钟钓鱼数的减少量用di表示,John从任意一个湖走到它下一个湖的时间用ti表示. 求一种方案,使得John在有限的

[poi2011]bzoj 2277 —— strongbox&#183;[洛谷3518]

·问题描述· 有一个密码箱,0到n-1中的某些数是它的密码.且满足:如果a和b都是它的密码,那么(a+b)%n也是它的密码.某人试了k次密码,前k-1次都失败了,最后一次成功. 问:该密码箱最多有多少个密码? ·输入格式· 输入第一行两个整数分别表示n,k. 第二行为k个用空格隔开的非负整数,表示每次试的密码.(数据保证存在合法解) ·输出格式· 输出一行一个数,表示结果. ·输入样例· 42 5 28 31 10 38 24 ·输出样例· 14 ·数据范围· 对于100%的数据:1<=k<=