1. 程式人生 > >luogu題解 UVA1615 【Highway】

luogu題解 UVA1615 【Highway】

min LG https sizeof 左右 pac stream 不難 題目

  • 題目鏈接:

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;
}

luogu題解 UVA1615 【Highway】