SDOI2012 拯救小云公主(二分+搜索)

满分做法:

其实就是二分+奶酪那个题,二分不合法的情况为左边界联通到下边界和右边界,上边界连接到下边界和右边界。

#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
const int maxm=3100;
const double eps=1e-5;
int k,n,m,tot;
double xx[maxm],yy[maxm];
int q[maxm];
bool vis[maxm];
double ans,rr;
bool flag=0;
double dis(int x,int y)
{
 return sqrt((xx[x]-xx[y])*(xx[x]-xx[y])+(yy[x]-yy[y])*(yy[x]-yy[y]));	
}
void dfs(int x)
{
 vis[x]=1;
 if((n-xx[x]<rr)||(yy[x]-1.0<rr))
 {
  flag=1;
  return;
 }
 for(int i=1;i<=k;i++)
 {
  if(vis[i]) continue;
  if(dis(x,i)<2*rr)
  {
    dfs(i);
    if(flag)
    return;
  }
 }	
}
bool check(double x)
{
 tot=0;
 rr=x;
 flag=0;
 for(int i=1;i<=k;i++)
 {
   vis[i]=0;
   if((xx[i]-1.0<rr)||(m-yy[i]<rr))
   q[++tot]=i;
 }
 for(int i=1;i<=tot;i++)
 {
  if(!vis[q[i]])
  {
    dfs(q[i]);
    if(flag)
    return 0;
  }
 }
 return 1;
}
int main()
{
 scanf("%d%d%d",&k,&n,&m);
 for(int i=1;i<=k;i++)
 scanf("%lf%lf",xx+i,yy+i);
 double l=0,r=max(n,m);
 while(l+eps<=r)
 {
  double mid=(l+r)/2.0;
  if(check(mid))
  {
    ans=mid;
    l=mid+eps;
  }
  else r=mid-eps;
 }
 printf("%.2lf\n",ans);
 return 0;	
}
posted @ 2019-11-06 09:03  lihan123  阅读(128)  评论(0编辑  收藏  举报