您的位置:首页 > 其它

1288 汽油补给(贪心+单调栈)

2017-08-17 21:48 204 查看
1288 汽油补给


题目来源: Codility

基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题


 收藏


 关注

有(N+1)个城市,0是起点N是终点,开车从0 -> 1 - > 2...... -> N,车每走1个单位距离消耗1个单位的汽油,油箱的容量是T。给出每个城市到下一个城市的距离D,以及当地的油价P,求走完整个旅途最少的花费。如果无法从起点到达终点输出-1。
例如D = {10, 9, 8}, P = {2, 1, 3},T = 15,最小花费为41,在0加上10个单位的汽油,在1加满15个单位的汽油,在2加2个单位的汽油,走到终点时恰好用完所有汽油,花费为10 * 2 + 15 * 1 + 2 * 3 = 41。

Input
第1行:2个数N, T中间用空格分隔,N + 1为城市的数量,T为油箱的容量(2 <= N <= 100000, 1 <= T <= 10^9)。
第2至N + 1行:每行2个数D[i], P[i],中间用空格分隔,分别表示到下一个城市的距离和当地的油价(1 <= D[i], P[i] <= 1000000)。


Output
输出走完整个旅程的最小花费,如果无法从起点到达终点输出-1。


Input示例
3 15
10 2
9 1
8 3


Output示例

41

/*
贪心,首先,不能到达目的地的可能只有一个,那就是车的容量不够,实际上可以枚举当前的城市,然后去计算当前的城市的油价一直到后面哪个城市都是最小的,设这个数为y,当前城市为x,那么从x到y+1中间的道路消耗的油都应该尽量在x加。显然,对于每个城市的y是可以用O(n)的时间用单调栈处理出来的,那么剩下枚举也是O(n)了
*/
#include<cstdio>
#include<iostream>
#include<queue>
#define ll long long
using namespace std;
const int mn=100005;
ll n,t,d[mn],p[mn],st[mn],r[mn],top=0;
ll s[mn];
int main() {
scanf("%lld%lld",&n,&t);
for(int i=1; i<=n; ++i) {
scanf("%lld%lld",&d[i],&p[i]);
s[i]=s[i-1]+d[i];
}
for(int i=n; i>0; --i) {
if(d[i]>t) {
puts("-1");
return 0;
}
//往右边找小于p[i]的坐标的最小位置
while(top>0&&p[st[top-1]]>=p[i]) --top;
r[i]=top==0?n+1:st[top-1];
st[top++]=i;
}
int cnt=0;//剩余的油量
ll ans=0;
for(int i=1; i<=n; ++i) {
ll ad=s[r[i]-1]-s[i-1];
ll tt=min(ad,t)-cnt;//需要加的油
if(tt<=0) {
cnt-=d[i];
continue;
}
ans+=tt*p[i];//需要的价钱
cnt+=tt-d[i];
}
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: