luogu题解 UVA1615 【Highway】

  • 题目链接:

https://www.luogu.org/problemnew/show/UVA1615

  • 分析:

首先这里的距离是欧几里得距离而不是曼哈顿距离。

然后我们对于每个点,求出在公路上保持D范围内最远的两个端点,这两个端点构成一个区间,我们要做的就是选出尽量少的点使所有区间至少有一个点,就是典型的区间选点问题。

怎么做呢?把所有区间右端点从小到大排序,如果右端点相同左端点小的在前面。

达到贪心的目的,我们设一个pos=-inf,然后遍历所有区间,如果pos>该区间左端点,cnt+1,pos=区间右端点,然后结合之前的排序方式就不难理解。

  • 注意:

  • 可能有些人不知道怎么求左右端点,这要用到一点解析几何知识,每个点\((a,b)\)构成一个圆的方程\((x-a)^2+(y-a)^2=d^2\),然后将\(y=0\)带入就求出两个横坐标

  • 有多组数据

  • 代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
using namespace std;
const int maxn=1000005;
struct Seg{
    double l,r;
    bool operator <(const Seg &b)const{
        if(r==b.r)return l>b.l;
        return r<b.r;
    }
}seg[maxn];
double l,d;
int n;
int main(){
    
    while(scanf("%lf %lf %d",&l,&d,&n)!=EOF){
    int cnt=0;
    for(register int i=1;i<=n;i++){
        double x,y;
        scanf("%lf %lf",&x,&y);
        double sqr=sqrt(d*d-y*y);
        seg[i].l=max(0.0,-sqr+x);
        seg[i].r=min(l,sqr+x);
    }
    sort(seg+1,seg+1+n);
    double pos=-19260817.0;
    for(register int i=1;i<=n;i++){
        if(seg[i].l>pos){
            pos=seg[i].r;
            cnt++;
        }
    }
    printf("%d\n",cnt);
    memset(seg,0,sizeof(seg));
    }
        return 0;
}

猜你喜欢

转载自www.cnblogs.com/Rye-Catcher/p/9089877.html
今日推荐