牛客 Guard the empire(贪心)

首先看到题目求最小覆盖,应该可以想到是贪心类的问题

题目要求覆盖所有骨龙,首先所有骨龙都会在一段区间内被覆盖,我们可以算出每个骨龙的这段距离。

之后就是求有多少个点可以将这些区间全部覆盖,这是贪心的经典问题。

显然是先排序,以第一个点的右端点为初始值,往下遍历,如果某个左端点大于他,那么更新为当前的右端点,++ans

否则,如果当前的右端点小于他,更新为右端点,这个需要理解一下,因为我们当前的右端点并不能覆盖它,也就是这两个区间是包含关系,所以就用类似反悔的方法,把这个点的右端点设为答案。

注意double,但是这题如果按右端点排序,更加好写

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<double,double> pll;
const int N=2e5+10;
pll p[N];
int d,n;
void cal(int a,int b,int i){
    p[i].x=(double)a-sqrt(double(d*d-b*b));
    p[i].y=(double)a+sqrt(double(d*d-b*b));
}
void work(){
    sort(p+1,p+1+n);
    double pos=p[1].y;
    int ans=1;
    for(int i=2;i<=n;i++){
        if(p[i].x>pos){
            ++ans;
            pos=p[i].y;
        }
        else if(p[i].y<pos)
            pos=p[i].y;
    }

    cout<<ans<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    int cnt=0;
    while(cin>>n>>d){
        if(!n&&!d)
            return 0;
        int i;
        int flag=0;
        int a,b;
        for(i=1;i<=n;i++){
            cin>>a>>b;
            if(d<b||flag){
                flag=1;
                continue;
            }
            cal(a,b,i);
        }
        cout<<"Case "<<++cnt<<":"<<" ";
        if(flag)
            cout<<-1<<endl;
        else{
            work();
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12988126.html