题目大意:有一条从南到北的道路,根据最南建筑到北的方向延伸,有一系列的坐标,这条道路上有一些点,一共有n个朋友(这些点里一个点一个朋友),他们任一个站立在xi米的地方,可以沿着道路的两个方向的任何一个方向,以不超过每秒6米的速度移动:南或北。你要计算在路上的某个时刻收集所有n个朋友所需的最短时间。(注意:他们最短时间内达到的共同位置不一定为整数坐标)
解题思路:这个题看懂了应该就明白是二分了,关键是怎么去二分,首先我想着二分距离,但是,因为求的是时间,如果二分距离,根本枚举不完,因为这个位置可以是小数,所以换思路,枚举时间,二分判断能不能在二分出的时间mid内求出这个最小时间,在排序后的点里,先提出第一个点(最左边那一个),再用循环,将点两两比较,取交集直到取出全部的共同交集,如果有则为所求时间,如果没有则继续二分。
我这代码……还是调了好几遍细节才出来的……
代码奉上:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5;
int n;
double ans;
struct node
{
int x,v;
bool operator < (const node &a)const
{
return x<a.x;
}
} mapn[maxn];
bool erfen(double mid) //判断二分出来的时间够不够用
{
double time;
double a=mapn[1].x-mapn[1].v*mid; //之前写的int wa了……
double b=mapn[1].x+mapn[1].v*mid;
for(int i=2; i<=n; i++)
{
double c=mapn[i].x-mapn[i].v*mid;
double d=mapn[i].x+mapn[i].v*mid;
if(a<c) a=c;
if(b>d) b=d;
if(a>b) return false;
}
return true;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
scanf("%d",&mapn[i].x);
for(int i=1; i<=n; i++)
scanf("%d",&mapn[i].v);
sort(mapn+1,mapn+n+1);
double l=0,r=1e9;
double mid;
while(r-l>1e-6)
{
mid=(l+r)/2;
bool flag=erfen(mid);
if(flag)
{
ans=mid;
r=mid;
}
else
{
l=mid;
}
}
printf("%.12lf\n",ans); //没手动控制精度,也wa 了
}
return 0;
}
~step by step