贪心算法--加油站、公路问题

1 篇文章 0 订阅
1 篇文章 0 订阅

题目来自洛谷-P9749,传送门

题目描述

小苞准备开着车沿着公路自驾。

公路上一共有 n n n 个站点,编号为从 1 1 1 n n n。其中站点 i i i 与站点 i + 1 i + 1 i+1 的距离为 v i v_i vi 公里。

公路上每个站点都可以加油,编号为 i i i 的站点一升油的价格为 a i a_i ai 元,且每个站点只出售整数升的油。

小苞想从站点 1 1 1 开车到站点 n n n,一开始小苞在站点 1 1 1 且车的油箱是空的。已知车的油箱足够大,可以装下任意多的油,且每升油可以让车前进 d d d 公里。问小苞从站点 1 1 1 开到站点 n n n,至少要花多少钱加油?

输入格式

输入的第一行包含两个正整数 n n n d d d,分别表示公路上站点的数量和车每升油可以前进的距离。

输入的第二行包含 n − 1 n - 1 n1 个正整数 v 1 , v 2 … v n − 1 v_1, v_2\dots v_{n-1} v1,v2vn1,分别表示站点间的距离。

输入的第三行包含 n n n 个正整数 a 1 , a 2 … a n a_1, a_2 \dots a_n a1,a2an,分别表示在不同站点加油的价格。

输出格式

输出一行,仅包含一个正整数,表示从站点 1 1 1 开到站点 n n n,小苞至少要花多少钱加油。

样例 #1

样例输入 #1

5 4
10 10 10 10
9 8 9 6 5

样例输出 #1

79

提示

【样例 1 解释】

最优方案下:小苞在站点 1 1 1 买了 3 3 3 升油,在站点 2 2 2 购买了 5 5 5 升油,在站点 4 4 4 购买了 2 2 2 升油。

【数据范围】

对于所有测试数据保证: 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1n105 1 ≤ d ≤ 1 0 5 1 \leq d \leq 10^5 1d105 1 ≤ v i ≤ 1 0 5 1 \leq v_i \leq 10^5 1vi105 1 ≤ a i ≤ 1 0 5 1 \leq a_i \leq 10^5 1ai105


原因分析:

提示:我先自己手动模拟了一下,假设我自己去加油,我会先在第1站加油开去第2站,第2站的油价比第3更便宜,但是比第4站的油价高,所以我就开两站去第4站,最后从第4站开到终点站第5段。总之就是哪站便宜我就加油,直到我看到更便宜的油价的加油站我才停下来。
(每次都加目前最便宜的油,体现贪心!)


解决方案:

提示:代码注释写的比较详细,方便自己下次能看懂


```cpp

#include<bits/stdc++.h>
using namespace std;
int main()
{
	long long int n,d,cnt,minn,weizhi=0,ans=0;//cnt表示每次加的几升油,minn是取最少的油价 ,每一站都要对比的 
	cin>>n>>d;//weizhi表示,我目前的油还能走到的下一段还剩的距离,比如买了3升油可以走12公里,但是到下一站只需要10,所以weizhi=12-10=2 
	long long int dis[100005],oil[100005];
	for(int i=1;i<=n-1;i++)
	   cin>>dis[i];
	for(int i=1;i<=n;i++)
	  cin>>oil[i];
	minn=oil[1];//不管贵不贵,肯定要从站1开始走 
	for(int i=1;i<=n-1;i++) //总共是n-1段路,要算账n-1次 
	{
		//cnt=ceil((dis[i]-weizhi)*1.0/d);
		if(i==1)//第一个站 特判一下
		{
			ans+=ceil((dis[i]-weizhi)*1.0/d)*oil[i];
			cnt=ceil((dis[i]-weizhi)*1.0/d);//ceil是向上取整的意思
		}
		else//i>=2
		{
			if(oil[i]<minn)//这站的油价比上一站(不止上一站,是比我最便宜的油价)还便宜,那更新minn,在这一站买 
			{
				minn=oil[i];
				cnt=ceil((dis[i]-weizhi)*1.0/d);
				ans=ans+cnt*minn;//几升油*油价 =总钱 
			
			}
			else//这站的油价比我之前的油价更贵,那就不在这一站买,在我最便宜的时候多买一站--由结果来推导我之前的决定。
			     //就是说,比如我这站贵,那我就在上一站多买一站 ,如果下一站还是比我Minn贵,我就继续买 ,直到比我minn更小的时候才停下来加油 
			{
				cnt=ceil((dis[i]-weizhi)*1.0/d);
				ans=ans+cnt*minn;//这里的minn没有更新,还是用的原来的便宜油价 
				
			} 		
		}
		
		weizhi=cnt*d-(dis[i]-weizhi);//每一站都要更新weizhi !
	}
	cout<<ans;
	return 0;
}

如果有问题可以在评论区指出~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值