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;
}






目录
打赏
0
0
0
0
15
分享
相关文章
uva 10340 all in all
输入两个字符串s和t,判断是否可以从t中删除0个或多个字符(其他字符顺序不变),得到字符串是。
52 0
UVa10123 No Tipping
UVa10123 No Tipping
71 0
UVa11776 - Oh Your Royal Greediness!
UVa11776 - Oh Your Royal Greediness!
62 0
UVa 10082 WERTYU
Problem Description A common typing error is to place the hands on the keyboard one row to the right of the correct position.
898 0
uva 11806 - Cheerleaders
点击打开链接 题意:在一个n行m列的矩形里面放k个相同的石子,要求第一行,最后一行,第一列,最后一列都要有石子。问有几种方法? 思路: 1 如果题目没有要求“第一行,最后一行,第一列,最后一列都要有石子”,那么答案就是C[n*m][k],我们用C[i][j]表示i个里面选择j个的组合数。
833 0
uva 12470 Tribonacci
点击打开uva12470  思路: 矩阵快速幂 分析: 1 裸题 代码: /************************************************ * By: chenguolin ...
1000 0
uva 1160 X-Plosives
点击打开链接uva 1160 思路: 并查集 分析: 1 看懂题目之和就是切菜了 代码: #include #include #include #include using namespace std; const int MAXN...
782 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等