• 喷水装置


    https://loj.ac/problem/10002

    题目描述

      有n个喷头,每个喷头都在花坛的一定位置,每个喷头有一定的喷水的半径,使一个长L,宽W米的花坛全部被水淋到,求至少需要开几个喷头。无法满足则输出-1。

    思路

      我们把花坛这个二维的矩形看成一维的线段,那么喷头的有效喷水距离可以看为每个喷头喷水范围与花坛边缘的两交点的长度,即(s[i].l= pos-sqrt{r^2-(frac{w}{2})^2},s[i].r=pos+sqrt{r^2+(frac{w}{2})^2}),不过注意(r<frac{w}{2})的喷头是“无用的”。那么问题就转化为已知(n)个区间和一条线段,求选取最少的区间全部覆盖这条线段。那么我们只需将区间按左端点降序排序,假设现已满足([1,t])区间,顺序寻找区间,找到满足是(s[i].l<=t)的右端点最大的区间,更新(t=s[i].r)即可。判断无法覆盖时也就比较显然了。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    struct aa
    {
        double l,r;
    }a[15500];
    bool cmp(aa x,aa y)
    {
        return x.l<y.l;
    }
    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=0;i<n;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                if(y<=w/2)continue ;
                a[++cnt].l=(double)x-sqrt(y*y-w*w/4.0);
                a[cnt].r=(double)x+sqrt(y*y-w*w/4.0);
            }
            sort(a+1,a+cnt+1,cmp);
    //        for(int i=1;i<=cnt;i++)
    //            printf("%lf %lf
    ",a[i].l,a[i].r);
            double t=0;int ans=0,i=1;
            bool f=1;
            while(t<l)
            {
                ans++;
                double s=t;
                for(;a[i].l<=s&&i<=cnt;i++)
                    if(t<a[i].r)t=a[i].r;
                if(t==s&&s<l)
                {
                    f=0;
                    printf("-1
    ");
                    break ;
                }
            }
            if(f)printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    SAP程序代码中RANGE表的用法注意点
    代码审计学习-1
    应用层隧道之HTTP/HTTPS和DNS
    应用层隧道技术之SSH
    横向移动-常用windows连接和相关命令
    基于MSF的路由转发
    渗透过程中的边界突破(内部分享笔记)
    网络层隧道之PowerCat
    网络层隧道之lcx和nc的使用
    网络层隧道构建之PingTunnel
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11753812.html
Copyright © 2020-2023  润新知