您的位置:首页 > 其它

【bzoj2328】[HNOI2011]赛车游戏

2017-03-31 22:55 232 查看
题目链接

Description



题解

从耗油量最少开始慢慢贪心地调整。

对于上坡,速度设为0,但是免不了耗油,这一部分的耗油先减掉。

对于下坡,速度在不耗油的前提下设到最大(但是不能超过vmax)。

对于平路,速度设为0。

然后我们用一个优先队列来维护这些线段,每次取出速度最小的段,如果它的速度和次小的速度一样就合并起来,否则将它的速度提升到和次小的速度一样,当然这是在油够用的前提下,如果油不够用就提到能提到的最高速率。

这样做直到用光油或者都打到vmax时结束。

看起来挺对的。。是吧?

#include<bits/stdc++.h>
using namespace std;

typedef double db;

const db eps = 1e-9;

struct Node{
db v, x;
Node(){}
Node(db a, db b){v = a, x = b;}
bool operator < (const Node &a)const{
return v > a.v;
}
};
db a, b, vmax, f;
int n;
bool ok;
priority_queue<Node> q;

inline int fcmp(db x){
if(fabs(x) < eps) return 0;
else return x > 0 ? 1 : -1;
}
inline db sqr(db x){return x * x;}

void init(){
scanf("%lf%lf%lf%lf%d", &a, &b, &vmax, &f, &n);
db x, y, s, l;
ok = true;
for(int i = 1; i <= n; i++){
scanf("%lf%lf", &x, &y);
x /= 1000.0, y /= 1000.0;
s = y / x; l = sqrt(sqr(x) + sqr(y));
if(fcmp(s) > 0){
f -= l * b * s;
q.push(Node(0, l));
if(fcmp(f) <= 0) ok = false;
}
else if(fcmp(s) < 0)
q.push(Node(min(-s * b / a, vmax), l));
else q.push(Node(0, l));
}
}

void solve(){
if(!ok){
puts("IMPOSSIBLE");
while(!q.empty()) q.pop();
return;
}
q.push(Node(vmax, 0));
Node u, v;
db w;
db ans = 0;
while(fcmp(f) > 0 && !q.empty()){
u = q.top(); q.pop();
v = q.top();
if(!fcmp(u.v - vmax)) ans += u.x / u.v;
else if(fcmp(u.v - v.v)){
w = f / (a * u.x);
if(fcmp(u.v + w - v.v) >= 0){
w = v.v - u.v;
q.pop(); q.push(Node(v.v, u.x + v.x));
}
else{
u.v += w;
q.push(u);
}
f -= a * w * u.x;
}
else{
q.pop();
q.push(Node(v.v, u.x + v.x));
}
}
while(!q.empty()){
u = q.top(); q.pop();
ans += u.x / u.v;
}
printf("%.5lf\n", ans);
}

void work(){
int t; scanf("%d", &t);
while(t--){
init();
solve();
}
}

int main(){
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: