Star Way To Heaven题解(防题目重复)

题目描述

小 w 伤心的走上了 Star way to heaven。
到天堂的道路是一个笛卡尔坐标系上一个 n*m 的长方形通道 顶点在 (0,0) 和 (n,m) 。
小 w 从最左边任意一点进入,从右边任意一点走到天堂,最左最右的距离为 n,上下边界距离为m 。
其中长方形有 k 个Star ,每个 Star 都有一个整点坐标,Star 的大小可以忽略不计。
每个 Star 以及长方形上下两个边缘宇宙的边界都有引力,所以为了成功到达 heaven 小 w 离他们越远越好。
请问小 w 走到终点的路径上,距离所有星星以及边界的最小距离最大值可以为多少?

输入格式

一行三个整数n,m,k。
接下来 k 行,每行两个整数 表示一个点的坐标。

输出格式

一行一个数表示答案。保留到小数点后9位。

样例
样例输入
10 5 2
1 1
2 3
样例输出
1.118033989
数据范围与提示

对于 100% 的数据:k ≤ 6000;n,m ≤ 1 0 6 10^6 106

解析

求最小值的最大值,首先不难想到用二分求解,来二分答案,再来判断(老套路了)。但是,聪明的我发现这种算法时间复杂度为O( n 2 ∗ l o g ( n ) n^2*log(n) n2log(n))。再看看n的取值范围,明显会超时,据说是80分。
其实这道题要用到最小生成树。然后聪明的我就对了

  1. 先把所有点连接上边界
    在这里插入图片描述
  2. 最小生成树连接相邻点(假设所有点相邻,这里方便就连了1,2两点)进行prim,连接直接可以在prim里面连接。如果一个点的半径能够触碰到最下面,那就说明,已经成功封闭了
    (如果刚好封闭就是最小值)
    在这里插入图片描述
    在这里插入图片描述
    (注:上述图片纯属瞎搞 仅供参考,实际请以代码为准 )
  3. 最后输出最大连线距离,因为这是两个点的半径,所以要除以2

代码

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define ll long long
const int MAXN = 1e7 + 5;
ll x[MAXN], y[MAXN];
double d[MAXN];
bool v[MAXN];
int n, m, k;
double ans;
double calc(ll x, ll y, ll x2, ll y2) {
    
    
    return sqrt(((x - x2) * (x - x2) + (y - y2) * (y - y2)));
}
void Read() {
    
    
	scanf("%d %d %d", &n, &m, &k);
    for(int i = 1; i <= k; i++)
        scanf("%lld %lld", &x[i], &y[i]);
    for(int i = 1; i <= k; i++)
		d[i] = y[i];
    d[k + 1] = m;
}
void Prim() {
    
    
	for(int j = 1; j <= k + 1; j++) {
    
    
		int minn = 0;
		for(int i = 1; i <= k + 1; i++)
        	if(!v[i] && (d[i] < d[minn] || minn == 0))
				minn = i;
    	ans = max(ans, d[minn]);
    	if(minn == k + 1)
    		break;
    	v[minn] = 1;
    	for(int i = 1; i <= k; i++)
			d[i] = min(d[i], calc(x[i], y[i], x[minn], y[minn]));
    	d[k + 1] = min(d[k + 1], (m - y[minn]) * 1.0);
	}
    printf("%.9lf", ans / 2.0);
}
int main() {
    
    
	Read();
	Prim();
    return 0;
}

求求你点个赞再走,我的图真的很用心了
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Face_the_Blast/article/details/108062331
way