BZOJ2328: [HNOI2011]赛车游戏

BZOJ2328: [HNOI2011]赛车游戏

Description


题解Here!

 

一开始被题面那一长串的描述吓到了,一直没敢做。。。
然后尝试着硬着头皮读懂题面。
然后。。。这不是贪心么???

从耗油量最少开始慢慢贪心地调整。
对于上坡,速度设为$0$,但是免不了耗油,这一部分的耗油先减掉。
对于下坡,速度在不耗油的前提下设到最大(但是不能超过$vmax$)。
对于平路,速度设为$0$。
然后我们用一个优先队列来维护这些线段,每次取出速度最小的段,如果它的速度和次小的速度一样就合并起来,否则将它的速度提升到和次小的速度一样。

当然这是在油够用的前提下,如果油不够用就提到能提到的最高速率。
这样做直到用光油或者都打到$vmax$时结束。
证明?$\tan(\frac{\pi}{2}+k\pi),k\in Z$。。。

附代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<queue>
#define eps (1e-8)
using namespace std;
int n;
double A,B,maxn,f;
bool flag;
struct node{
    double oil,dis;
    friend bool operator <(const node &p,const node &q){
        return p.oil>q.oil;
    }
};
priority_queue<node> q;
inline int check(double x){
    if(fabs(x)<eps)return 0;
    return (x>0?1:-1);
}
void work(){
    if(!flag){
        printf("IMPOSSIBLE\n");
        while(!q.empty())q.pop();
        return;
    }
    double w,ans=0;
    node u,v;
    q.push((node){maxn,0});
    while(check(f)>0&&!q.empty()){
        u=q.top();
        q.pop();
        v=q.top();
        if(check(u.oil-maxn)==0)ans+=u.dis/u.oil;
        else if(check(u.oil-v.oil)!=0){
            w=f/(A*u.dis);
            if(check(u.oil-v.oil+w)>=0){
                w=v.oil-u.oil;
                q.pop();
                q.push((node){v.oil,u.dis+v.dis});
            }
            else{
                u.oil+=w;
                q.push(u);
            }
            f-=A*w*u.dis;
        }
        else{
            q.pop();
            q.push((node){v.oil,u.dis+v.dis});
        }
    }
    while(!q.empty()){
        u=q.top();
        q.pop();
        ans+=u.dis/u.oil;
    }
    printf("%.5lf\n",ans);
}
void init(){
    double x,y,w,l;
    scanf("%lf%lf%lf%lf%d",&A,&B,&maxn,&f,&n);
    flag=true;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&x,&y);
        x/=1000.0;y/=1000.0;
        w=y/x;
        l=sqrt(x*x+y*y);
        if(check(w)>0){
            f-=w*B*l;
            q.push((node){0,l});
            if(check(f)<=0)flag=false;
        }
        else if(check(w)<0)q.push((node){min(-w*B/A,maxn),l});
        else q.push((node){0,l});
    }
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        init();
        work();
    }
    return 0;
}

 

posted @   符拉迪沃斯托克  阅读(238)  评论(0编辑  收藏  举报
Live2D
欢迎阅读『BZOJ2328: [HNOI2011]赛车游戏』
点击右上角即可分享
微信分享提示