引论:贪心算法作为算法学习中的一种重要思想,其重要性和实用性不言而喻。在解决实际问题中,贪心算法总能引领我们得出问题的最优解,而它由于动态规划算法不同,它是通过贪心选择性质和最优子结构性质确定解法,然后自顶而下解决问题,下面分享我对第四章——贪心算法的学习心得。
一、对贪心算法算法的理解
首先我们要知道,贪心算法并不是从整体最优上加以考虑的,它所做的选择只是在某种意义上的局部最优选择。但是,若所求问题的整体最优解可以通过一系列局部最优解得到,那么我们就可以以迭代的方式将所求问题简化为问题规模更小的子问题,那么贪心算法就能有效地解决问题。使用贪心算法,要求我们:1. 首先找到合理的贪心策略,即如何选择来实现得到最优解的情况。 2. 列出一系列贪心选择策略后,一个个证明其可行性,最后通过证明得出可行的贪心选择策略。 3. 利用得出的贪心选择策略来解决当前的子问题。 4. 由于整体问题的最优解包含每个子问题的最优解,所以最后能够得出整体问题的最优解。
二、以作业题为例子分析贪心算法
问题事例:
问题分析:首先,汽车想要使沿途的加油次数最少,则需要最大利用汽车每次加了的油。每次我们先分析加满油的汽车能走n公里,结合每个加油站的距离,即能得到每次加满油能够经过的加油站次数。题目要求要得到达到目的地的最少加油次数,那么我们可以求出每次加油的能经过的加油站,并在最后一个加油站加油,这样既是整体问题的子问题的最优解——得出全程最少的加油次数。最终,各个子问题最优解能够得到整体问题的最优解。
解题参考代码
1 #include <iostream> 2 using namespace std; 3 4 void showMin(int n, int k, int distances[]) 5 { 6 int min = 0; 7 for (int i = 0; i < k + 1; i++) 8 { 9 if (distances[i] > n) //判断能不能达到终点 10 { 11 cout << "No Solution!"; 12 return; 13 } 14 } 15 16 for (int i = 0, temp = 0; i <= k + 1; i++) //如果能够到达目的地 17 { 18 temp += distances[i]; 19 if (temp > n) //当油量不足时,加油次数增加, 20 { 21 min++; 22 temp = distances[i]; 23 } 24 } 25 cout<<min; 26 } 27 28 int main() 29 { 30 int n, k; //n表示满油情况下能跑的距离,k表示沿途的加油站数目 31 cin >> n >> k; 32 int distances[k + 1]; 33 34 for (int i = 0; i < k + 1; i++) 35 { 36 cin >> distances[i]; //输入相邻两点的距离 37 } 38 39 showMin(n, k, distances); 40 return 0; 41 }
需要特别注意的是,若有两个相邻的加油站的距离大于汽车加满油能行驶的距离,那么汽车不可能到达目的地,也不可能得到最优解。
三、在本章学习中遇到的问题及结对编程情况
虽然贪心算法相比于动态规划算法简单,但其思想却不简单。在学习贪心算法并尝试解题的时候,我经常会犯没有证明贪心选择策略是否可行就直接使用的错误。这样不仅导致了时间的浪费,同时是对贪心算法掌握不熟悉的反映。
同时,即是贪心算法很实用,但很多时候解题我们都没有想到使用,没有看透题目的本质是要求我们使用贪心算法来解决,这也是我对贪心算法不熟悉的结果。在结对编程中,虽然我和搭档一起做实验的时候效果没有上两次好,但
两人的思想碰撞和一人编程实现贪心算法、一人证明贪心选择的可行性是一种不错的分工。对于本章的作业题,有些时候使用结构体排序是一种实现贪心算法的方式,而当结对编程的时候,我们能够充分运用结构体和排序算法。当
然,通过结对编程讨论、证明作业题的贪心策略,并一步步解决问题,也是一个令人激动的过程。