luogu题解 UVA1615 Highway
Posted rye-catcher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
",cnt);
memset(seg,0,sizeof(seg));
}
return 0;
}
以上是关于luogu题解 UVA1615 Highway的主要内容,如果未能解决你的问题,请参考以下文章
uva 1615Highway(算法效率--贪心 区间选点问题)