记录编号 570894 评测结果 AAAAAA
题目名称 喷水装置 最终得分 100
用户昵称 Gravatar惠惠 是否通过 通过
代码语言 C++ 运行时间 0.232 s
提交时间 2022-04-25 21:08:39 内存使用 3.04 MiB
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;
    
int T;
    
struct Sprinkler    //给喷水装置存为结构体,包含勾股定理后的喷水范围,装置位置,喷水半径
{
    double range, x, r;
}sprinkler[15010];

struct Suitable
{
    int xiabiao;
    double right;
};
    
bool cmp(const Sprinkler& a, const Sprinkler& b)    //cmp函数给sort排序使用(根据位置从左往右排序)
{
    if(a.x < b.x) return true;
    else return false;
}

bool cmp2(const Suitable& a, const Suitable& b)
{
    if(a.right > b.right) return true;
    else return false;
}

int main()
{
    freopen("sprinkler.in","r",stdin);
    freopen("sprinkler.out","w",stdout);
    cin >> T;
    for(int group = 1; group <= T; ++group)     //循环T组
    {
        int n, spr_cnt = 0, ans = 0;    //定义:喷水装置总数,有效喷水装置数,最终答案数
        double L, W;
        cin >> n >> L >> W;     //输入
        for(int i = 1; i <= n; ++i)     //循环n次,输入有效喷水装置,无效装置(半径小于W/2)直接舍去
        {
            double x, r;
            cin >> x >> r;
            if(r > W / 2)
            {
                ++spr_cnt;
                sprinkler[spr_cnt].r = r;
                sprinkler[spr_cnt].x = x;
            }
        }
        sort(sprinkler + 1, sprinkler + spr_cnt + 1, cmp);      //根据位置从左往右排序
        for(int i = 1; i <= spr_cnt; ++i)       //求出并存贮每个有效装置使用勾股定理求出的喷水范围
        {
            sprinkler[i].range = sqrt(sprinkler[i].r * sprinkler[i].r - (W / 2) * (W / 2));
        }
        int start = 0;      //定义:当前被选取装置中最右边的装置的下标(目前没有选取任何装置,故为0)
        for(int i = spr_cnt; i >= 1; --i)       //从右向左,找能覆盖到草最左边的 最靠右的装置
        {
            if(sprinkler[i].range >= sprinkler[i].x)
            {
                start = i;
                ++ans;
                break;
            }
        }
        if(start == 0)      //如果未找到能覆盖到草地左边的装置,本组无解,输出-1
        {
            cout << -1 << endl;
            continue;
        }
        double left = sprinkler[start].x + sprinkler[start].range;      //定义:当前被覆盖范围的最右边
        if(left >= L)
        {
            cout << ans << endl;
            continue;
        }
        for(int i = start + 1; i < spr_cnt; )
        {
            Suitable suit_spr[spr_cnt - start + 1];
            int cnt = 0;
            for(int j = i; j <= spr_cnt; ++j)
            {
                if(sprinkler[j].x - sprinkler[j].range <= left)
                {
                    ++cnt;
                    suit_spr[cnt].xiabiao = j;
                    suit_spr[cnt].right = sprinkler[j].x + sprinkler[j].range;
                }
            }
            if(cnt == 0) break;
            if(cnt > 1) sort(suit_spr + 1, suit_spr + cnt + 1, cmp2);
            left = suit_spr[1].right;
            i = suit_spr[1].xiabiao + 1;
            ++ans;
            if(left >= L)
            {
                cout << ans << endl;      //如果最后的装置可以覆盖草地最右边,则输出答案数
                break;
            }
        }
        // for(int i = spr_cnt; i > start; )       //从右向左,找能覆盖 当前覆盖范围最右边 的装置,并更新覆盖范围
        // {
        //     if(sprinkler[i].x - sprinkler[i].range <= left)     //找到符合上述条件的装置
        //     {
        //         left = sprinkler[i].x + sprinkler[i].range;     //更新覆盖范围
        //         start = i;      //更新被选取装置中最右边的装置
        //         i = spr_cnt;    //重新从最右边开始寻找
        //         ++ans;          //答案数+1
        //         continue;
        //     }
        //     --i;        //若本装置不能覆盖当前范围的最右边,则找下一个
        // }  
        if(left < L) cout << -1 << endl;      //若不能,则无解,输出-1
    }
    return 0;
}