CodeForces 782B The Meeting Place Cannot Be Changed(二分)

题目大意:有一条从南到北的道路,根据最南建筑到北的方向延伸,有一系列的坐标,这条道路上有一些点,一共有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

发布了37 篇原创文章 · 获赞 23 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/zsheng_/article/details/78312154
今日推荐