C++贪心实现汽车加油问题

一、实验目的

1.掌握基于贪心的算法求解汽车加油问题的原理和贪心性质的证明。

2.掌握汽车加油问题贪心算法正确性的推导过程和设计原理。

3.掌握基于贪心的算法汽车加油问题函数的具体步骤。

4.具备运用贪心算法的思想设计算法并用于求解其他实际应用问题的能力。

5.深刻体会贪心算法求解问题的便利和贪心算法对于计算机求解该问题的优化以及是如何简化计算步骤和减少求解问题时间的。

二、实验环境

操作系统:Windows10

实验平台:VisualStudio Code

编译器:g++

实验语言:C++

实验终端:WindowsPowerShell

三、实验内容

现给出一辆汽车,该汽车加满油后一共可以行驶n km,行驶旅途中一共有k个加油站,汽车加油问题要解决的是,设计一个有效的算法,该算法应给出应该在哪些加油站停靠加油,使得沿途加油次数最少。即给定的n和k个加油站的位置,计算出最少加油次数。

程序输入,第一行输入两个整数n和k,表示汽车加满油后可行驶n km,路途中加油站的个数为k个。第二行输入k+1个整数,这些整数表示第k个加油站与k-1个加油站之间的距离。第0个加油站为汽车出发地,已加满油,第k+1个加油站为目的地,所有k+1个数字之和即为汽车需要行驶的路程。

程序输出,要求计算出最少加油次数并给出,如果无法达到目的地,需要输出“No Solution”。若给出n和k为7,加油站之间的距离为1 2 3 4 5 1 6 6,则通过计算可知最少加油次数为4。

四、算法描述

问题分析,设汽车现在已经加满油,设加油次数为f,每个加油站之间的距离为dist[i],i=0,1,2,3,4…,n为汽车加满油后可以行驶的距离,k为加油站的个数,有如下情况:

  1. :出发点距目的地的距离小于n,加油次数为0,无需加油即可到达目的地。

  1. :出发点距目的地的距离大于n,则若各个加油站之间的距离等长且距离等于n,加油次数至少为k次,若各个加油站之间的距离等长且距离大于n,则无法达到目的地,若各个加油站之间的距离等长且距离小于n,加油次数为

  1. :加油站之间的距离不等长,可以通过贪心算法求解。

贪心算法求解该问题的主要思想为: 需要检查每一小段路程是否超过汽车满油量时的最大支撑路程。如果有超过的,那么汽车不可能走完这段路。否则,找到汽车满油量时的最大支撑路程范围内的最后一个加油站,加油后继续用此方法前进。

求解该问题的贪心选择性质:

贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的贪心选择来达到。对于一个具体的问题,要证明它具有贪心性质,必须确保每一步所作的贪心选择最终导致问题的一个整体最优解。

在该问题中,在汽车总共可以行使的n千米路程中,取两个加油站A和B,A加油站靠近出发点,B加油站远离出发点,可知,如果在B加油站加油不能到达目的地,则在A加油站加油也不能到达目的地。根据贪心选择性质,为了使得加油的次数最少,则每次都会选择距离可以加满油的加油站远一点的加油站取加油,即加油次数满足贪心选择性质。

求解该问题的最优子结构性质:

最优子结构性质为,问题的整体最优解包含着问题的子问题的最优解。若当前已经得到前一段路程的一个满足贪心选择性质的最优解,即该段路程中,在第一个加油站加油时,该最优解是该路程中加油次数最少的最优解,即每次汽车中剩下的油,若不能行驶到下一个加油站时,才需要在该加油站加满油。

每一个类似的过程都满足贪心性质,每一次加满油后都与起点具有相同的条件且这些过程相互独立,即加油次数具有最优子结构性质。用相同的方式递归求解下去,最终每个阶段的最优解合并为原问题的解,就可以得到原问题的求解。

贪心算法的时间复杂度:

要想知道需要在哪个加油站加油需要遍历每一个加油站,每个加油站只需遍历一次,该算法的时间复杂度为O(n)。

算法实现步骤:

  1. :初始化dist数组以及ans变量(用以记录加油的次数)设置tmp为0。

  1. :循环遍历dist数组,若数组中某个数字(代表两个加油站之间的距离)大于n,则无论如何选择加油站加油,都无法到达最终目的地。程序返回-1,并告知用户结果。

  1. :循环遍历dist数组,累计当前已经行驶的路程,若行驶路程大于n,则需要在上一个加油站或当前加油站加油,使用ans记录加油次数并输出当前选择的加油站序号。

  1. :计算得到最终结果并返回。

实现贪心思的主要代码片段:

for (int i = 0;i <= k; i++){

tmp +=dist[i];

if (tmp> n){

ans++;

tmp =dist[i];

cout<< i << " ";}

}

五、实验结果

第一组输入,设汽车加满油后可以行驶的距离为7 km,行驶旅途中加油站的个数为7个,各个加油站之间的距离为:1,2,3,4,5,1,6,6。通过程序编程求解得到的结果是:为顺利到达 目的地,需要在3,4,6,7加油站加油,最少的加油次数为4。

第二组输入,设汽车加满油后可以行驶的距离为100 km,行驶旅途中加油站的个数为7个,各个加油站之间的距离为:6,6,6,6,6,6,6,6。即汽车可行驶距离远远大于各个加油站之间的距离,通过程序编程求解得到的结果是:为顺利到达目的地,无需加油,加油次数为0。

第三组输入,设汽车加满油后可以行驶的距离为1 km,行驶旅途中加油站的个数为7个,各个加油站之间的距离为:2,3,4,5,6,7,8,9。即汽车可行驶距离小于各个加油站之间的距离,通过程序编程求解得到的结果是:无法到达目的地,这辆车可行使距离太短。

六、实验总结

本次实验从汽车加油问题的实际需求出发,生动形象的展示了贪心算法在生活中的实用性,我深刻体会到了贪心算法求解的便利性。同时我也学到,在贪心算法的思想中,每次做出的选择(贪心选择)都应该是在当前的情况下所能做出的最好的选择,以达到局部最优选择。接下来解决做出这个局部最优选择后产生的其他子问题。

然而同时需要注意到,不是每一个问题都适用贪心算法,使用贪心算法并不能解决一些问题的整体最优解,为使用贪心算法,需要求该问题具有贪心选择性质和贪心的最优子结构性质。

本次的代码实现并无难点,按照算法分析即可写出编程实现,然而我在写for循环时,误将i<=k写成i<k,导致算出的结果比需要加油的次数少1,还好通过debug后认识到了这个问题,这个教训告诉我一定要注意编程中的细节,少迭代一次都会得到错误的结果。

通过这次求解实现汽车加油问题的实验,增加了我对编程实现的严谨性以及堆贪心算法贪心选择和贪心最优子结构性质的再次认识,以及认识到不是每一个问题都适用于贪心算法,要具体问题具体分析。

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值