您的位置:首页 > 其它

ZOJ 3699 Dakar Rally 解题报告

2013-05-20 22:27 281 查看
题意:给油箱容量,n个有顺序的点,给出从当前点到下一个点的距离,单位耗油量,汽油的单价。每个站都能加不超过油箱容量的油。求到终点的最小花费。

解法:本着贪心的原则,应该尽量在便宜的地方多加油。

所以模拟汽车行驶的过程中,在比当前位置汽油便宜的站能加要尽量加满(如果之后发现不是最优的就减去),并记录每一站剩余的可用油量,和到当前站油箱中剩余的汽油(因为要保证不超过油箱容量)。而花费是统计从当前站恰好到下一站使用的最便宜的汽油的价钱,即队首汽油。
用单调队列维护还能加油的区间的单价最小值,每次需要加油的时候只需要从队首取油就行,用完即可出队列。

//Memory: 4876 KB
//Time: 250 MS
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;
const int maxn = 200005;
const int inf = 1111111111;
long long q[maxn],head,tail,cost[maxn];
long long p[maxn];

int main()
{
//freopen("in.txt","r",stdin);
int ca,n,m,use[maxn];
int u,v;
long long w;
bool flag;
scanf("%d",&ca);
while(ca--)
{
scanf("%d%d",&n,&m);
flag = 1;
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d",&u,&v,&p[i]);
w=(long long)u*v;
if(w>m) flag = 0;
else cost[i]=u*v;
}
if(flag == 0)
{
printf("Impossible\n");
continue;
}
head = tail = 0;
long long ans = 0;
long long gas=0;
for(int i = 1; i <= n; i++)
{
while(head<tail&&p[i]<p[q[tail-1]]) gas-=use[--tail];
use[tail]=m - gas;
q[tail++]=i;
//cout<<gas<<" "<<m-gas<<endl;
gas = m - cost[i];
//cout<<gas<<endl;
while(cost[i])
{
if(use[head]<=cost[i])
{
cost[i]-=use[head];
ans+=use[head]*p[q[head]];
head++;
}
else
{
use[head]-=cost[i];
ans+=cost[i]*p[q[head]];
cost[i]=0;
}
}
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: