uva 10382 - Watering Grass

简介: 点击打开链接uva 10382 题目意思:     有一块草坪,长为l,宽为w  ,在它的中心线上装有n个点状的喷水装置 , 效果是让以它为中心半径为ri的圆被润湿  , 选择尽量少的喷水装置把整个草坪全部润湿。

点击打开链接uva 10382


题目意思:    

有一块草坪,长为l,宽为w  ,在它的中心线上装有n个点状的喷水装置 , 效果是让以它为中心半径为ri的圆被润湿  , 选择尽量少的喷水装置把整个草坪全部润湿。


解题思路:  

1:贪心,区间覆盖

2:这道题就是一个区间覆盖的变形,只是没有那么的直观而已。刚开始区间求错了,直接求出最左边和最右边的左边以此来作为区间端点,后来WA了近20次才发现考虑错了,嗨,只怪自己思维不够严谨。真正的区间求法是,把这个圆和这个矩形两边的交点的横坐标求出来就是区间的端点值,注意这里由于圆很大所以左边或右边可能超过规定的长度L,所以求区间时候我们不用考虑L,因为没有影响,最后只要按照区间覆盖的思路就可以求出最小的区间数。

3:区间完全覆盖问题
    1 问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线  段可以将整个区间完全覆盖

    2 样例:
       区间长度8,可选的覆盖线段[2,6],[1,4],[3,6],[3,7],[6,8],[2,4],[3,5]

    3解题过程:
       1将每一个区间按照左端点递增顺序排列,拍完序后为[1,4],[2,4],[2,6],[3,5],[3,6],[3,7],[6,8]

       2设置一个变量表示已经覆盖到的区域。再剩下的线段中找出所有左端点小于等于当前已经覆盖到的区域的右端点的线段中,右端点最大的线段在加入,直到已经覆盖全部的区域

       3过程:
        假设第一步加入[1,4],那么下一步能够选择的有[2,6],[3,5],[3,6],[3,7],由于7最大,所以下一步选择[3,7],最后一步只能选择[6,8],这个时候刚好达到了8退出,所选区间为3

    4贪心证明:
      需要最少的线段进行覆盖,那么选取的线段必然要尽量长,而已经覆盖到的区域之前的地方已经无所谓了,(可以理解成所有的可以覆盖的左端点都是已经覆盖到的地方),那么真正能够使得线段更成的是右端点,左端点没有太大的意义,所以选择右端点来覆盖


代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

const int MAXN = 10010;
int n;
double len , wide;
struct seg{
    double left;
    double right;
    bool operator<(const seg& s1)const{
        if(left < s1.left)
          return true;
        else if(left == s1.left && right > s1.right)
          return true;
        return false;
    }
};
seg s[MAXN];

int solve(){
    if(s[0].left > 0)
      return -1;
    int ans = 1;
    double pre = 1e-8;
    for(int i = 0 ; s[i].left <= 0 && i < n ; i++)
        pre = max(pre , s[i].right);
    while(1){
        if(pre >= len) return ans;
        double Max = 1e-8;
        for(int i = 0 ; s[i].left <= pre && i < n ; i++)
           Max = max(Max , s[i].right);
        if(Max <= pre) return -1;
        else{
           ans++;
           pre = Max;
        }
    }
}

int main(){
    int pos;
    double d , r;
    while(scanf("%d%lf%lf" , &n , &len , &wide) != EOF){
        pos = 0;
        for(int i = 0 ; i < n ; i++){
           scanf("%lf%lf" , &d , &r);
           double tmp = sqrt(r*r-(wide/2.0)*(wide/2.0));
           s[pos].left = d-tmp;
           s[pos++].right = d+tmp;
        }
        sort(s , s+n);
        printf("%d\n" , solve());
    }
    return 0;
}






目录
相关文章
uva375 Inscribed Circles and Isosceles Triangles
uva375 Inscribed Circles and Isosceles Triangles
66 0
|
算法
UVA题目分类
题目 Volume 0. Getting Started 开始10055 - Hashmat the Brave Warrior 10071 - Back to High School Physics 10300 - Ecological Premium 458 - The Decoder 494...
1578 0
|
机器学习/深度学习
uva 12470 Tribonacci
点击打开uva12470  思路: 矩阵快速幂 分析: 1 裸题 代码: /************************************************ * By: chenguolin ...
998 0
uva 10273 Eat or Not to Eat?
点击打开链接uva 10273 思路: 暴力求解 分析: 1 题目要求没有吃掉的奶牛的个数已经最后一次吃掉奶牛的天数 2 没有其它的方法只能暴力,对于n头牛的n个周期求最小公倍数,然后在2个公倍数之内暴力求解 代码: #inclu...
837 0
uva 10730 - Antiarithmetic?
点击打开链接uva 10730 思路:枚举等差中项 分析: 1 给定一个n个数的序列判断是否有等差子序列 2 很明显我们如果要判断是否有等差子序列的话,只要去判断是否有长度为3的等差子序列 3 对于n
852 0
|
机器学习/深度学习 并行计算 AI芯片
刘汝佳uva 字符串专题
第一题   palindrome 点击打开链接uva 401 题目意思:给定一个字符串判断是什么类型 分析: 1 根据输出我们知道这个字符串总共有4种类型 2 首先应该是否是“palindrome ”,判断的理由很简单直接对这个...
1144 0
uva10340 Ail in All
题意:输入两个字符串s和t,判断是否可以从t种删除0个或多个字符(其他字符不变),得到字符串s,比如abcde可以得到bce,单数无法得到dc 分析:简单模拟即可 1 #include 2 #include 3 #include 4 #define zz 5 usin...
581 0