题意
给定一个长方形,长方形内有一些点。问从左下角走到右上角,离那些点的最远距离是多少。
解题思路
虽然简单,但想了很久。
二分,点变成了圆。问是否能够存在一条路径,不碰到圆,从左下角走到右上角。
比赛的时候卡了我2个小时,严重影响节奏啊!!!!!
并查集。
如果有交点,那么直接圆/边归入一集。
然后判断一下4条边是否在一个集合即可。
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define N 2010
#define DB double
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
struct note{
DB x,y;
}a[N];
int i,j,k,l,n,m;
int f[N],st,en;
DB x,y,L,R,Mid,ans,eps;
DB MIN;
int read(){
int rs=0,fh=1;char ch;
while((ch<'0'||ch>'9')&&(ch^'-'))ch=getchar();
if(ch=='-')fh=-1,ch=getchar();
while(ch>='0'&&ch<='9')rs=(rs<<3)+(rs<<1)+(ch^'0'),ch=getchar();
return rs;
}
DB dis(DB X1,DB X2,DB Y1,DB Y2){
return (X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2);
}
int get(int x){
return f[x]==x?x:f[x]=get(f[x]);
}
void merge(int x,int y){
int gx=get(x),gy=get(y);
if(gx^gy)f[gy]=gx;
}
bool check(DB Mid){
int i,j;
fo(i,1,n+4)f[i]=i;
fo(i,1,n){
if(a[i].x<Mid)merge(n+1,i);
if(x-a[i].x<Mid)merge(n+2,i);
if(a[i].y<Mid)merge(n+3,i);
if(y-a[i].y<Mid)merge(n+4,i);
}
fo(i,1,n-1)fo(j,i+1,n){
if(dis(a[i].x,a[j].x,a[i].y,a[j].y)<4*Mid*Mid){
merge(i,j);
}
}
f[n+1]=get(f[n+1]);
f[n+2]=get(f[n+2]);
f[n+3]=get(f[n+3]);
f[n+4]=get(f[n+4]);
if(f[n+1]==f[n+2]||f[n+1]==f[n+3])return 0;
if(f[n+2]==f[n+4]||f[n+4]==f[n+3])return 0;
return 1;
}
int main(){
scanf("%lf%lf%d",&x,&y,&n);
fo(i,1,n){
k=read(),l=read();
a[i].x=1.0*k;a[i].y=1.0*l;
}
eps=1e-4;
L=0,R=min(x,y)/2.0;ans=0;
while(R-L>eps){
Mid=(L+R)/2.0;
if(check(Mid))ans=Mid,L=Mid+eps;
else R=Mid-eps;
}
printf("%.2lf",ans);
return 0;
}