782B. The Meeting Place Cannot Be Changed
二分查找
double minp=0xfffffffff,9个f,题目里范围是10^9,一个f转换成二进制是4个1,应该表示10^9位的数的最大值,不知道int能不能这么用……
目标点应当是,这个点南边的所有点到这个点所花费的时间中最长的时间l,等于这个点北边的所有点到这个点所花费的时间中最长的时间h,这样时间才是最短的!max(t1…tn)=max(t1…tm)
二分坐标,查找坐标,low是所有点坐标最小值,high是所有点坐标最大值,mid=(high+low)/2,然后求出h和l(一个循环遍历所有点),判断这个mid是否满足上述条件(l==h),如果h>l,点应该右移,即low=mid,如果h<l,目标点应该左移,即high=mid
#include<bits/stdc++.h>
using namespace std;
double p[60005],v[60005];
int main()
{
int i,n;
double maxp=0,minp=0xfffffffff;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%lf",&p[i]);
maxp=max(maxp,p[i]);
minp=min(minp,p[i]);
}
for(i=0;i<n;i++)
scanf("%lf",&v[i]);
double low=minp, high=maxp, mid;
double h=0,l=0;
while(high-low>=1e-7)
{
mid=(low+high)/2;
h=0,l=0;
for(i=0;i<n;i++)
{
if(p[i]>=mid)
h=max(h,(p[i]-mid)/v[i]);
else
l=max(l,(mid-p[i])/v[i]);
}
if(h==l) break;
else if(h>l) low=mid;
else if(h<l) high=mid;
}
printf("%.12lf\n",(h+l)/2);
return 0;
}
二分查找,最开始是给定一个值,在一个有序列表(设为从小到大)里查找这个数的位置,先将目标值与区间中点比较,大于中点,则将区间左端点移到mid,(区间范围右移了,减少了一半),小于则相反,加粗部分即为二分思想的体现,每次查找能缩小一半范围,时间复杂度O(logn)
然后演变成,答案是不知道的,要在一个范围内查找这个答案,先设这个答案是范围的中点mid(二分思想体现),这个答案是要满足一定条件的(如此题mid左右两边最大时间相等,类比原始二分查找的目标值与mid单纯比大小),根据条件的满足情况(如mid左边的时间大于或小于右边的时间),将范围的某个端点移到中点mid,逐渐缩小范围,再符合一定精度,从而找到最终答案