TZOJ.6864.安全距离(二分+广搜)
Posted 须藤要
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TZOJ.6864.安全距离(二分+广搜)相关的知识,希望对你有一定的参考价值。
原题链接: link.
描述
新冠肺炎肆虐,严重影响了人们的正常生活,哪怕戴口罩出去也要尽可能与人群保持距离。
现有一条呈矩形的马路,长n,宽m,马路上有k个人,假设都固定不动(人的大小可以忽略,可计作点)。你想要从马路一端穿越到另一端,求你在穿越过程中能与其他人始终保持的安全距离最大可能是多少?
输入
第一行输入n,m(0<n, m<=100)和k(1<=k<=100),表示马路的长度,宽度和人数。
接下来有k行,每行两个整数x和y(0<=x<=n, 0<=y<=w),表示每个人所在的位置。
输出
输出一个小数,表示你在穿越过程中能与其他人始终保持的最大安全距离,结果保留2位小数。
样例输入
100 2 2
49 0
51 2
样例输出
1.41
题解
- 题目的意思是是否有一条可通过路径使他与每个人的距离尽量的大。因此我们可以二分每个人的安全距离来确定是否有一条路径可以通过。
- 假设n为10,m为4,三个点依次如下的情况,很明显当半径为1的时候可以通过的
-而这种情况是不能通过的 - 很明显当所有相交圆形成的区域的宽度大于路的宽度时,人就不能通过。
- 因此我们可以从y=0的情况开始出发,寻找是否存在一个区域的宽度大于路的宽度,假如存在,人就不能通过,否则反之。之后我们就可以用二分来依次枚举最大距离为r的时候,人是否可以通过
- 二分判断的check可以用广搜来实现,我们从y=0的时候出发,寻找是否存在一个点在r的范围之内,然后加入队列中,当队列中出来的圆y轴的最远距离大于m那么这就是不能通过,最后当队列中没有数时那么肯定存在一条路径使人通过。
AC代码
#include <cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
struct aa{
int x,y;
}p[101];
int n,m,k;
bool st[101];
bool cmp(aa a,aa b){
return a.y<b.y;
}
bool check(double mid){
memset(st,0,sizeof(st));
queue<aa>que;
for(int i=0;i<k;i++){
if(p[i].y<=mid){
que.push({p[i].x,p[i].y});
st[i]=1;
}
}
while(que.size()){
aa b=que.front();que.pop();
int x=b.x,y=b.y;
//存在一个区域的宽度大于m
if(y+mid>m)return 0;
//可用list进行优化
for(int i=0;i<k;i++){
if(!st[i]){
double s=sqrt((x-p[i].x)*(x-p[i].x)+(y-p[i].y)*(y-p[i].y));
if(s<=2*mid){
que.push({p[i].x,p[i].y});
st[i]=1;
}
}
}
}
return 1;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<k;i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
//把点以y从小到达排序
sort(p,p+k,cmp);
double l=0,r=m;
//二分
while(fabs(r-l)>0.00001){
double mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
printf("%.2lf",l);
return 0;
}
以上是关于TZOJ.6864.安全距离(二分+广搜)的主要内容,如果未能解决你的问题,请参考以下文章