1. 程式人生 > 其它 >P2498 [SDOI2012]拯救小云公主

P2498 [SDOI2012]拯救小云公主

考慮二分答案。

如何 check ?明顯不能進入的區域是以怪物為圓心,mid為半徑的圓。兩個圓是否聯通就看\(dis(i,j)\)是否大於\(2\times mid\)。然後並查集判斷是否能有縫隙通過即可。

容易發現與上下、左右邊界聯通時不能找到縫隙。

#include<bits/stdc++.h>
using namespace std;
int n,row,line;
int fa[3005];
double mx[3005],my[3005];
int f(int x){
	return x==fa[x]?x:fa[x]=f(fa[x]);
}
double dis(double x1,double y1,double x2,double y2){
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool check(double w){
	for(int i=0;i<=n+1;i++)fa[i]=i;
	for(int i=1;i<n;i++){
		for(int j=i;j<=n;j++){
			if(dis(mx[i],my[i],mx[j],my[j])<=2*w)fa[f(i)]=f(j);
		}
	}
	for(int i=1;i<=n;i++){
		if(mx[i]-w<=1||my[i]+w>=line)fa[f(i)]=f(0);
        if(mx[i]+w>=row||my[i]-w<=1)fa[f(i)]=f(n+1);
	}
	return f(0)!=f(n+1);
}
int main(){
	cin>>n>>row>>line;
	for(int i=1;i<=n;i++)cin>>mx[i]>>my[i];
	double l=0,r=114514;
	while(r-l>1e-5){
		double mid=(l+r)/2;
		if(check(mid))l=mid;
		else r=mid;
	}
	printf("%.2lf",l);
	return 0;
}

會TLE。可以選擇把精度調到\(10^{-3}\),或者吸口老氧。

YJX AK IOI