1 条题解

  • 0
    @ 2024-10-29 10:07:54

    解析: 按各喷头起点从小到大排序,优先选能覆盖当前起点,且终点最大的。 注意,如果喷洒半径小于W/2,则该喷头可以忽略。

    #include<bits/stdc++.h>
    using namespace std;
    struct node {
        double b,e;//每个喷头覆盖的起点和终点
    }a[15005];
    bool cmp(node x,node y){
        return x.b<y.b;
    }
    int T;
    int n,L,W;
    int main() {
        cin>>T;
        while(T--){
            cin>>n>>L>>W;
            for(int i=1;i<=n;i++){
                int p,r;
                cin>>p>>r;
                a[i].b=0;
                a[i].e=0;
                if (r>=W/2.0){
                    a[i].b=p-sqrt(r*r-W*W/4.0);
                    a[i].e=p+sqrt(r*r-W*W/4.0);
                }
            }
            sort(a+1,a+1+n,cmp);//按起点从小到大排序
            int cnt=0;//需要的喷头数量
            double s=0;//起点
            double t=0;//终点
            int i=1;//从第一个喷头开始
            bool flag=1;//假定有解
            while (t<L){//只要没覆盖完
                cnt++;//增加一个喷头
                s=t;//起点为上次的终点
                for(;a[i].b<=s&&i<=n;i++){//枚举可以覆盖起点的喷头
                    t=max(t,a[i].e);//找到最大覆盖的终点
                }
                if(s==t&&t<L){//如果没有覆盖起点的喷头并且终点没有覆盖整个区间
                    flag=0;
                    cout<<-1<<endl;//无解
                    break;
                }
            }
            if (flag==1){//有解
                cout<<cnt<<endl;
            }
        }
        return 0;
    }
    

    信息

    ID
    608
    时间
    1000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者