P2498 [SDOI2012]拯救小云公主

(color{#0066ff}{ 题目描述 })

英雄又即将踏上拯救公主的道路……

这次的拯救目标是——爱和正义的小云公主。

英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss。当英雄意识到自己还是等级1的时候,他明白这就是一个不可能完成的任务。

但他不死心,他在想,能不能避开boss去拯救公主呢,嘻嘻。

Boss的洞穴可以看成一个矩形,英雄在左下角(1,1),公主在右上角(row,line)。英雄为了避开boss,当然是离boss距离越远越好了,所以英雄决定找一条路径使到距离boss的最短距离最远。

Ps:英雄走的方向是任意的。

你可以帮帮他吗?

当英雄找到了美丽漂亮的小云公主,立刻就被boss包围了!!!英雄缓闭双眼,举手轻挥,白光一闪后使用了回城卷轴,回到了城堡,但只有小云公主回去了……因为英雄忘了进入回城的法阵了。

(color{#0066ff}{输入格式})

第一行,输入三个整数,n表示boss的数目,row,line表示矩形的大小;

接下来n行,每行分别两个整数表示boss的位置坐标。

(color{#0066ff}{输出格式})

输出一个小数,表示英雄的路径离boss的最远距离,精确到小数点后两位。

(color{#0066ff}{输入样例})

1 3 3
2 2
    
1 3 3
3 1

(color{#0066ff}{输出样例})

1.00
    
2.00

(color{#0066ff}{数据范围与提示})

20%数据,boss坐标范围小于等于50;

60%数据,n<=1500;

100%数据,n<=3000;

(color{#0066ff}{ 题解 })

显然要二分答案

于是,问题就变成了二维奶酪(见NOIP2017 奶酪

(O(n^2logn)),卡卡二分就过了

#include<bits/stdc++.h>
#define LL long long
LL in() {
	char ch; LL x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
	return x * f;
}
const int maxn = 3505;
int n;
bool flag;
double X, Y;
struct node {
	double x, y;
	node(double x = 0, double y = 0): x(x), y(y) {}
}e[maxn];
std::vector<int> v[maxn];
bool vis[maxn];
double D[maxn][maxn];
std::queue<int> q;
bool ok(double mid) {
	while(!q.empty()) q.pop();
	for(int i = 1; i <= n; i++) {
		if(e[i].x < mid || Y - e[i].y < mid) q.push(i), vis[i] = true;
		else vis[i] = false;
	}
	while(!q.empty()) {
		int tp = q.front(); q.pop();
		if(X - e[tp].x < mid || e[tp].y < mid) return false;
		for(int i = 1; i <= n; i++) if(!vis[i] && D[tp][i] < mid * mid * 4.0) vis[i] = true, q.push(i);
	}
	return true;
}
int main() {
	n = in(), X = in() - 1, Y = in() - 1;
	for(int i = 1; i <= n; i++) e[i].x = in() - 1, e[i].y = in() - 1; 
	for(int i = 1; i <= n; i++)
		for(int j = i + 1; j <= n; j++) {
			node a = e[i], b = e[j];
			D[i][j] = D[j][i] = (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
		}
	double l = 0, r = std::min(X, Y), ans = r;
	int t = 200;
	while(t--) {
		double mid = (l + r) / 2.0;
		if(ok(mid)) ans = mid, l = mid;
		else r = mid;
	}
	printf("%.2f", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/olinr/p/10357203.html