题解 P2498 【[SDOI2012]拯救小云公主】
BFS大火题
首先 标签里面写了,那我们就 二分答案
模型转化
把答案视为Boss的攻击半径,题目就变成了给你一个矩形中有一些圆,问能否找到一条从左下角到右上角的路径不经过任何一个圆(此类问题的常规操作)
如果我们把圆看成奶酪上的一些洞,则当左边界或上边界通过这些洞和右边界或下边界联通时问题无解
然后我们看到了[NOIP2017]奶酪
然后就做完了
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
using namespace std;
inline int gi() {
register int x, c, op=1;
while(c=getchar(),c<'0'||c>'9')if(c=='-')op=-op;
x=c^48;
while(c=getchar(),c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48);
return x*op;
}
int dis[3001][3001];
int x[3001],y[3001];
int getdis(int x1,int y1,int x2,int y2) {
return pow(x1-x2,2)+pow(y1-y2,2);
}
bool able(int d,double r) {
return r*r*4>d;
}
int row,line,n;
queue<int>q;
bool vis[3001];
bool bfs(double r) {
memset(vis,0,sizeof(vis));
while(!q.empty())q.pop();
for(int i=1;i<=n;i++)
if(x[i]<r||row-y[i]<r)q.push(i),vis[i]=1;
while(!q.empty()) {
int p=q.front();
q.pop();
if(line-x[p]<r||y[p]<r)return 0;
for(int i=1;i<=n;i++)
if(!vis[i]&&able(dis[p][i],r))vis[i]=1,q.push(i);
}
return 1;
}
int main() {
n=gi(),line=gi()-1,row=gi()-1;
for(int i=1;i<=n;i++)
x[i]=gi()-1,y[i]=gi()-1;
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
dis[i][j]=dis[j][i]=getdis(x[i],y[i],x[j],y[j]);
double l=0,r=min(row,line),mid;
for(int i=1;i<=60;i++) {
mid=(l+r)/2;
if(bfs(mid))l=mid;
else r=mid;
}
printf("%.2lf\n",l);
return 0;
}