• nyoj 题目12 喷水装置(二)


    喷水装置(二)

    时间限制:3000 ms  |  内存限制:65535 KB
    难度:4
     
    描述
    有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
     
    输入
    第一行输入一个正整数N表示共有n次测试数据。
    每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
    随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
    输出
    每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
    如果不存在一种能够把整个草坪湿润的方案,请输出0。
    样例输入
    2
    2 8 6
    1 1
    4 5
    2 10 6
    4 5
    6 5
    样例输出
    1
    2

    有些代码还是得自己想,别人的还是看不懂。
    先上代码
     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cmath>
     4 using namespace std;
     5 typedef pair<double,double> Segment;
     6 
     7 Segment seg[10002];
     8 
     9 Segment getSeg(int x, int r, int h2) {
    10     int p = r*r - h2*h2;
    11     double d = sqrt(p);
    12     double x0 = (double)x;
    13     Segment tmp(x0-d,x0+d);
    14     return tmp;
    15 }
    16 
    17 int cmp(const void *a, const void *b) {
    18     Segment at = *(Segment*)a;
    19     Segment bt = *(Segment*)b;
    20     return at.first - bt.first;
    21 }
    22 
    23 int main(int argc, char const *argv[])
    24 {
    25     int t;
    26     scanf("%d",&t);
    27     while(t--) {
    28         int n,w,h;
    29         scanf("%d %d %d",&n,&w,&h);
    30         int cnt = 0;
    31         int h2 = h/2;
    32         while(n--){
    33             int x,r;
    34             scanf("%d %d",&x,&r);
    35             if(r <= h2) {
    36                 continue;
    37             }
    38             seg[cnt++] = getSeg(x,r,h2);
    39         }
    40         qsort(seg, cnt, sizeof(Segment),cmp);
    41         int to = 0;
    42         int p = 0;
    43         int ans = 0;
    44         while(to < w) {
    45             int j = p;
    46             int maxTo = to;
    47             while(j < cnt && seg[j].first <= to) {
    48                 if(maxTo < seg[j].second) {
    49                     maxTo = seg[j].second;
    50                 }
    51                 j++;
    52             }
    53             if(j == p) {
    54                 break;
    55             }
    56             ans++;
    57             to = maxTo;
    58             p = j;
    59         }
    60         printf("%d
    ",ans);
    61     }
    62     return 0;
    63 }

    思路还是要转换成水平方向上的覆盖。这里要用到贪心的思想。

    中心思想就是,选择一个可以覆盖到当前末端并且覆盖最大的线段

  • 相关阅读:
    加密与解密学习笔记3-Windows与Unicode
    加密与解密学习笔记2-windows API函数
    加密与解密学习笔记1-文本编码方式
    python3基础知识自学笔记4-流程控制、迭代器、生成器
    python3基础知识自学笔记3-集合字典元组
    python3基础知识自学笔记2-列表
    在单链表按升序插入一个值
    [转]设置好ftp后用xftp连接提示无法打开,无法显示远程文件夹
    删除底部"自豪地采用 WordPress"
    win7一体机放音乐时只有音乐,人声特别小怎么回事
  • 原文地址:https://www.cnblogs.com/jasonJie/p/6086677.html
Copyright © 2020-2023  润新知