一 实验目的
熟练掌握贪心法的设计思想与技巧。
二 实验内容
一辆汽车加满油后可行驶n公里,旅途中有k个加油站。试用贪心法求解如下问题:汽车应在哪些加油站停靠加油,使沿途加油次数最少。
三 算法设计与编码
3.1问题分析
贪心法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望导致结果是最好或最优的算法-不能得到整体最优解而是局部最优解,关键在于策略的选择。
可行性分析:
1. 贪心选择性质:在每个步骤都选择局部最优解,从而希望导致全局最优解
在该问题中,局部最优解是在当前油量不足以到达下一个加油站时,在最近的加油站加油;
2. 最优子结构性质:问题的最优解包含了其子问题的最优解
汽车在每个加油站的加油决策,都会影响到最终需要加油的次数。从这个角度看,贪心策略是符合这种性质的,每次做出的加油决策都是基于当前最优的信息。
3.2算法设计
用贪心法解决此汽车加油问题的核心就是保证能走到离自己最远的加油站,也就是能走本加油站但走不到下一个加油站方在本加油站加油。
步骤:
1.获取用户输入数据:
汽车加满油后可行公里数n、旅途中的加油站数目k、各加油站距离(包括起始地目的地)。
2. 调用函数carrefuel(n,k,distances)获取汽车旅途中加油情况。
函数设计:
for循环遍历距离数组:
如果某段距离>汽车加满油之后的距离,汽车无法抵达目的地。
否则:
如果当前已行驶路程(加完油后)+到下一个加油站的距离<=汽车加 满油后可行驶公里数,那么汽车可以继续行驶,更新行驶路程。
否则:
汽车需要在这个加油站加一次油,更新行驶路程。
输出汽车应在哪些加油站停靠加油、总加油次数。
3.3核心代码
四 算法运行调试与分析
通过上面的分析可以看出,汽车加油问题分两种情况:
能顺利到达目的地的情况下加最少次数的油;
汽车因加油站之间距离过远无法行驶到下一加油站加油从而无法到达目的地。
下就如上情况给出下面两组调试分析:
测试1:
汽车加满油后可行驶公里数为100,到目的地途中有3个加油站,距离分别为50,50,50,50;运用贪心思想,最远可到达第2个加油站,在第二个加油站处加一次油,加满油后顺利到达目的地,最多加一次油。
测试2
汽车加满油后可行驶公里数为100,到目的地途中有3个加油站,距离分别为100,50,120,20;运用贪心思想,汽车最远可到达第一个加油站,加一次油,经第二个加油站,汽车即使加满油也无法到达第三个加油站,则汽车无法抵达目的地。
五 实验总结
本次实验中,我通过每次选择当前最优解(即在必要时加油)来寻找全局最优解(最少的加油次数)的贪心策略完成汽车加油问题的求解。此实验帮助我提升了编程能力和解决实际问题的能力,并加深了我对贪心算法适用条件(具有最优子结构特性的问题,并且该最优子结构能通过局部最优解推导得到)、核心思想(在每一步决策中都选择当前看起来最优的解,希望这样能得到全局最优解)的理解。
六 代码附录
package Carrefuel;
import java.util.Scanner;
public class Carrefuel{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入汽车加满油后可行驶公里数:");
int n=sc.nextInt();
System.out.println("请输入旅途中的加油站数目:");
int k=sc.nextInt();
int []distances=new int[k+1];
System.out.println("请输入出发地到第一个加油站的距离:");
distances[0]=sc.nextInt();
for(int i=1;i<k;i++){
System.out.println("请输入第"+i+"个加油站到第"+(i+1)+"个加油站之间的距离");
distances[i]=sc.nextInt();
}
System.out.println("请输入第"+k+"个加油站到目的地的距离:");
distances[k]=sc.nextInt();
carrefuel(n,k,distances);
}
public static void carrefuel(int n,int k,int[] distances){
int count=0;//加油次数
int distance=0;//可行驶最长段
for(int i=0;i<distances.length;i++){
if(distances[i]>n){
System.out.println("第"+i+"加油站和第"+(i+1)+"加油站间距离过远,汽车无法抵达目的地!");
break;
}else{
if(distance+distances[i]<=n){
distance+=distances[i];
}else{
count++;
System.out.println("汽车需要在第"+i+"个加油站加一次油!");
distance=distances[i];
}
}
}
System.out.println("汽车旅途中共加了"+count+"次油!");
}
}