POJ-1328 Radar Installation题解

Radar Installation(贪心)

题意

  假设在一条无限延伸的\(x\)轴上方存在\(n\)个点,现问是否能用多个在圆心在\(x\)轴上,半径为\(d\)的圆包含所有的点,若可以,输出最少的使用个数,不行则输出\(-1\)

思路

  先考虑不行的情况,只要点的离\(x\)轴的高度超过圆的半径\(d\),就不可能用圆来覆盖。
  接下来,我们可以先想一下两个点的情况,什么时候需要增加新的圆?设两个点分别为\(A、B\),并假设\(B\)\(A\)的右侧。能圈住\(A\)点并且向右覆盖范围最大的是当\(A\)点在圆上,此时圆心\(X_A\)的位置最靠右,只要\(B\)离圆心的距离大于半径,并且能圈住\(B\)并向右覆盖范围最大的圆的圆心\(X_B\)在点\(X_A\)的右侧,就需要新增加圆。其余的情况只需要调整\(X_A\)的位置,就可以覆盖到\(B\)点。

参考代码

点此展开
#include<iostream>
#include<cmath>
#include<algorithm>

using namespace std;

typedef long long LL;
typedef pair<int,int> PII;

const double eps=1e-6;
const int N=1010;

struct node
{
    double x,y;
    bool operator<(const node &a)
    {
        return x<a.x;
    }
}ns[N];

double get_pos(double y,double d)
{
    return sqrt(d*d-y*y);
}

double calc_dis(double cur,double x,double y)
{
    return sqrt(y*y+(x-cur)*(x-cur));
}

int main()
{
    #ifdef LOCAL
    freopen("D:/VSCodeField/C_Practice/a.in", "r", stdin);
    freopen("D:/VSCodeField/C_Practice/a.out", "w", stdout);
    #endif

    int kase=0;
    int n;
    double d;

    while(cin>>n>>d)
    {
        if(n==0&&d<eps)
            break;

        bool has=false;//是否有点不能被覆盖
        for(int i=0;i<n;i++)
        {
            cin>>ns[i].x>>ns[i].y;
            if(ns[i].y-d>eps)
                has=true;
        }

        cout<<"Case "<<++kase<<": ";
        if(has) cout<<-1<<endl;
        else
        {
            sort(ns,ns+n);

            int res=1;
            double cur=ns[0].x+get_pos(ns[0].y,d);

            for(int i=1;i<n;i++)
            {
                double next_pos=ns[i].x+get_pos(ns[i].y,d);
                if(calc_dis(cur,ns[i].x,ns[i].y)>d)
                {
                    if(next_pos>cur)
                        res++;
                    cur=next_pos;
                }
            }
            cout<<res<<endl;
        }
    }

    return 0;
}

posted @ 2021-06-16 22:09  Daneii  阅读(134)  评论(0)    收藏  举报