51nod汽油补给


 
李陶冶  (命题人)
基准时间限制:1 秒 空间限制:131072 KB 分值: 160
有(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
C++的运行时限为:1000 ms ,空间限制为:131072 KB  示例及语言说明请按这里


这题没什么好讲的啦

自己YY一下就好了

贪心的选择当前能到达的地点中费用最低的

然后就在那里买油啦

分类讨论一下只在那里买油够不够多走一个地点

够的话就先走到那里然后重复操作(此时仍可在最优点那买油,因为还没装满嘛,还可能在这继续买)

不够的话就在那里买满,然后到这个点的下一个点,重复

PS:细节有点多,自己慢慢处理啦

上代码:

#include<cstdio>
#include<cstring>
#include<queue>
const int N=100005;
long long int d[N],p[N];
long long su[N];
struct node
{
	long long int j,x;
	bool operator < (const node &y)
	const 
	{
		return x>y.x;
	}
};
std::priority_queue<node> q;
int main()
{
	int n,t;
	scanf("%d %d",&n,&t);
	for(int i=1;i<=n;i++)	scanf("%lld %lld",&d[i],&p[i-1]),su[i]=su[i-1]+d[i];
	int now=0;long long int sum=0;
	int v=0; int r;
	while(now<n)
	{
		int j=now;
		while(j<=n&&v>=su[j]-su[now])	q.push((node){j,p[j]}),j++;
		node u=q.top();q.pop();
		if(su[j]-su[u.j]<=t)	 r=v-su[j-1]+su[now],sum+=p[u.j]*(d[j]-r),v=v-su[u.j]+su[now]+(d[j]-r),now=u.j;
		else v-=su[u.j]-su[now],sum+=p[u.j]*(t-v),v+=t-v,v-=d[u.j+1],now=u.j+1;
		while(!q.empty())	q.pop();
	}
	printf("%lld\n",sum);
	return 0;
}




转载于:https://www.cnblogs.com/Brian551/p/7353026.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值