HDU 6581 Vacation

Vacation(HDU6581 杭电多校第一场1004 二分答案)

万物皆可用二分,出现最小就二分

题目描述
Tom and Jerry are going on a vacation. They are now driving on a one-way road and several cars are in front of them. To be more specific, there are n cars in front of them. The ith car has a length of li, the head of it is si from the stop-line, and its maximum velocity is vi. The car Tom and Jerry are driving is l0 in length, and s0 from the stop-line, with a maximum velocity of v0.
The traffic light has a very long cycle. You can assume that it is always green light. However, since the road is too narrow, no car can get ahead of other cars. Even if your speed can be greater than the car in front of you, you still can only drive at the same speed as the anterior car. But when not affected by the car ahead, the driver will drive at the maximum speed. You can assume that every driver here is very good at driving, so that the distance of adjacent cars can be kept to be 0.
Though Tom and Jerry know that they can pass the stop-line during green light, they still want to know the minimum time they need to pass the stop-line. We say a car passes the stop-line once the head of the car passes it.
Please notice that even after a car passes the stop-line, it still runs on the road, and cannot be overtaken.
输入
This problem contains multiple test cases.
For each test case, the first line contains an integer n (1≤n≤105,∑n≤2×106), the number of cars.
The next three lines each contains n+1 integers, li,si,vi (1≤si,vi,li≤109). It’s guaranteed that si≥si+1+li+1,∀i∈[0,n−1]
输出
For each test case, output one line containing the answer. Your answer will be accepted if its absolute or relative error does not exceed 10−6.
Formally, let your answer be a, and the jury’s answer is b. Your answer is considered correct if |a−b|/max(1,|b|)≤10−6.
The answer is guaranteed to exist.
样例输入
1
2 2
7 1
2 1
2
1 2 2
10 7 1
6 2 1
样例输出
3.5000000000
5.0000000000

题意
有n+1辆车在路口排队等着过红绿灯,可以假设一直都是绿灯,而且路太窄不能超车,后面的车赶上前面的车以后,可以和前车车尾距离为0,但不能推着前车走,只能减速跟着(后面的车减速)。你排在最后一位。给出你前面有n辆车,总共n+1辆的车头到红绿灯(题目里叫停车线)的距离、每辆车的车长、每辆车的最高速度,求你的车头到达红绿灯的最短时间。
最开始都以最高时速跑。
题解
二分答案,二分时间t。从第一辆车往自己的车跑。如果下一辆车超过当前位置,则新位置为当前位置减去车长。如果没有超过当前位置,则为此时车尾的位置。最后判断自己的车头是否超越了停车线。
当时用优先队列写,最先碰撞的出队巨麻烦 但还是二分是牛*。

附上代码

#include
#define mem(a,x) memset(a,x,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ull; // %llu
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = -1u>>1;
const int maxn = 1e6+5;
int n,st;
int chang[maxn],l[maxn],r[maxn],v[maxn];
bool check(double x)
{
    double cnt=l[n]+x*v[n];     //cnt为此时车尾的位置 下一辆车的车头不可能超过车尾
    for(int i=n-1; i>=1; i--)
    {
        if(r[i]+x*v[i]>cnt)
        {
            cnt-=chang[i];  //如果超过了,此时位置减去车长
        }
        else
            cnt=l[i]+x*v[i];    //如果没有超过。此时位置就是此处x时间后车尾的位置
    }
    if(cnt+chang[1]>=st)    //判断最后一辆车头是否过线
        return 1;
    return 0;
}
int main()
{
    while(~scanf("%d",&n))
    {
        n++;
        for(int i=1; i<=n; i++)scanf("%d",&chang[i]);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&l[i]);
            l[i]+=chang[i];
        }
        st=l[1];
        for(int i=1; i<=n; i++)
        {
            l[i]=st-l[i];
            r[i]=l[i]+chang[i];
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&v[i]);
        }
        //处理过后l[i]为车i的左端点也就是车尾,r[i]为车i的右端点也就是车头,v[i]为车i的最大速度,st为Tom的车头距离停车线距离
        int mm=*min_element(v+1,v+n+1);
        double ll=(st-r[1])*1.0/v[1],rr=(st-r[1])*1.0/mm+1,mid;  //注意ll rr的初值,但也可以ll=0,rr=1e9+5;
        while(rr-ll>1e-7)       //注意二分条件 需要ll-rr小于1e-6
        {
            mid=(ll+rr)/2;
            if(check(mid))
            {
                rr=mid;
            }
            else
            {
                ll=mid;
            }
        }
        printf("%.10lf\n",mid);
    }
}

总结下wa点

  1. cin 会超时。
  2. 二分r的初始值要设置成(车头与停车线的距离除去最小速度+1),不加常数会wa掉,也不知道为什么。但为了安全起见最好还是l的初始值为0,r的初始值为max。
  3. while(l-r<1e-7) 题目要求误差范围小于1e-6所以此处需要比1e-6更小。

水题 ,水题,水题!

自己好像弱智

你可能感兴趣的:(日常训练)