题目描述
小 w w w伤心的走上了 S t a r w a y t o h e a v e n Star way to heaven Starwaytoheaven。
到天堂的道路是一个笛卡尔坐标系上一个 n ∗ m n*m n∗m的长方形通道 顶点在 ( ( (顶点在 ( 0 , 0 ) (0,0) (0,0)和 ( n , m ) ) (n,m)) (n,m)) 。
小 w w w从最左边任意一点进入,从右边任意一点走到天堂,最左最右的距离为 n n n,上下边界距离为 m m m。
其中长方形有 k k k个 S t a r Star Star,每个 S t a r Star Star都有一个整点坐标, S t a r Star Star的大小可以忽略不计。
每个 S t a r Star Star以及长方形上下两个边缘 ( ( (宇宙的边界 ) ) )都有引力,所以为了成功到达 h e a v e n heaven heaven小 w w w离他们越远越好。
请问小 w w w走到终点的路径上,距离所有星星以及边界的最小距离最大值可以为多少?
输入格式
一行三个整数 n , m , k n,m,k n,m,k。
接下来 k k k行,每行两个整数 x i , y i xi,yi xi,yi表示一个点的坐标。
输出格式
一行一个数表示答案。保留到小数点后9位。
样例
样例输入
10 5 2
1 1
2 3
样例输出
1.118033989
算法分析
这道题可以二分,但是二分要超时,所以要用其他解法
1、所有点连接上边界(初始化)
2、最小生成树连接相邻点进行prim,连接直接可以在prim里面连接。如果一个点的半径能够触碰到最下面,那就说明已经成功封闭了。
3、最后输出最大连线距离,因为是两个点的半径,所以要除以2
注意:
这道题要用到坐标系上两点间长度
double Sqrt(edge x,edge y){
return sqrt((x.xi-y.xi)*(x.xi-y.xi)+(x.yi-y.yi)*(x.yi-y.yi));
}
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
const int M=1e6+5;
struct edge{
double xi,yi;
}G[M];
double dis[M];
bool flag[M];
int n,m;
double Sqrt(edge x,edge y){
return sqrt((x.xi-y.xi)*(x.xi-y.xi)+(x.yi-y.yi)*(x.yi-y.yi));
}
double Prim(){
double ans=0;
for(int i=1;i<=m;i++){
dis[i]=n-G[i].yi;
}
dis[m+1]=n;
for (int i=1;i<=m+1;i++){
int id=0;
for(int j=1;j<=m+1;j++){
if(!flag[j]&&(dis[j]<dis[id]||id==0)){
id=j;
}
}
ans=max(dis[id],ans);
if(id==m+1) break;
flag[id]=true;
for(int j=1;j<=m;j++){
dis[j]=min(dis[j],Sqrt(G[j],G[id]));
}
dis[m+1]=min(dis[m+1],G[id].yi);
}
return ans/2;
}
int main(){
scanf("%*d%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%lf %lf",&G[i].xi,&G[i].yi);
}
dis[m+1]=n;
printf("%.9lf",Prim());
return 0;
}