洛谷P1325 雷达安装

题目

https://www.luogu.com.cn/problem/P1325

思路

挺巧妙的一道题,刚开始又是想贪心,又是考虑决策单调性想搞DP,一直在想怎么把一个雷达覆盖的点最大化。

后来画了一下图,发现如果从岛屿的角度思考这题就很好做了。

首先,雷达必然在x轴上最优。(不解释)

我们发现,对于一个岛屿来说,能覆盖他的雷达位置的可行区间是一条线段,且其左右端点可以根据勾股定理计算。

那么,问题就转化成了,有若干条线段,要求放置一些点,使得每条线段上都至少有一个点。这就是一个经典的贪心问题了。

将线段按右端点从小到大排序,如果当前线段未被之前的点覆盖,就在该线段的最右端放一个点。

代码

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn (int)(2e6+10)
#define eps 1e-8
#define inf 0x3f3f3f3f
using namespace std;
struct point{
    int x,y;
} p[maxn];
struct line{
    double L,R;
    bool operator <(line t){
        return R<t.R;
    }
} l[maxn];
int main(){
    int n,d,flag=1,ans=0;
    scanf("%d%d",&n,&d);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&p[i].x,&p[i].y);
        l[i].L=p[i].x-sqrt(d*d-p[i].y*p[i].y);
        l[i].R=p[i].x+sqrt(d*d-p[i].y*p[i].y);
    }
    sort(l+1,l+n+1);
    for(int i=1;i<=n;i++){
        if(p[i].y>d){
            flag=0;
            break;
        }
    }
    if(flag){
        double last=-inf;
        for(int i=1;i<=n;i++){
            if(l[i].L-eps>last){
                ans++;
                last=l[i].R;
            }
        }
    }
    else{
        ans=-1;
    }
    printf("%d",ans);
    // system("pause");
    return 0;
}
posted @ 2021-03-23 21:15  文艺平衡树  阅读(28)  评论(0编辑  收藏  举报