寻找“最美”,贪心算法,我全都要
——算法第四章总结 软三 杨伟耿 20181003083
一、 以小见大,贪心策略
贪心算法总是做出在当前看来是最好的选择,贪心算法并不从整体最优上加以考虑,所做的选择只是在某种意义上的局部最优,当然我们也希望得到的最终结果也是整体最优的。在我看来,就是一个找“最”的过程,比如按最大排序、最小排序、平均最大等等。解体思路大致是,先寻找一个“最”,然后思考能否找出反例来推翻这个“最”,有反例的话就重新找“最”,直到可以通过反证法等证明该“最”是最优选择,且不存在反例。
汽车加油问题:
汽车加油问题 (15 分)
题目来源:王晓东《算法设计与分析》
一辆汽车加满油后可行驶 n公里。旅途中有若干个加油站。设计一个有效算法,指出应 在哪些加油站停靠加油,使沿途加油次数最少。
输入格式:
第一行有 2 个正整数n和 k(k<=1000 ),表示汽车加满油后可行驶n公里,且旅途中有 k个加油站。 第二行有 k+1 个整数,表示第 k 个加油站与第k-1 个加油站之间的距离。 第 0 个加油站表示出发地,汽车已加满油。 第 k+1 个加油站表示目的地。
输出格式:
输出最少加油次数。如果无法到达目的地,则输出“No Solution!”。
输入样例:
7 7
1 2 3 4 5 1 6 6
输出样例:
4
贪心选择性质:用一个变量sum记录用掉的汽油可行驶的公里数,当累加到超过最大公里数的时候就要加油,这时候用另一个变量记录次数。如果加油站距离太远(大于一次加油所能行驶的最远距离时,就无法到达,输出“No Solution!”)。
每次都尽可能得多行驶距离,不行就加油。
源代码如下:
1 #include <iostream>
2
3 using namespace std;
4
5 int main() {
6
7 int n,k,a[1001];
8
9 cin>>n>>k;
10
11 for(int i = 0; i <= k; i++) {
12
13 cin>>a[i];
14
15 }
16
17 if(a[k] > n) {
18
19 cout<<"No Solution!"<<endl;
20
21 return 0;
22
23 }
24
25 int sum = 0, p = 0;
26
27 for(int i = 0; i <= k; i++) {
28
29 sum += a[i];
30
31 if(sum > n) {
32
33 p++;
34
35 sum = a[i];
36
37 }
38
39 }
40
41 cout<<p<<endl;
42
43 return 0;
44
45 }
二、 结对编程,查漏补缺
贪心算法较为简单,需要一起讨论解题思路的情况较少,但很多打代码的细节和优化需要一起思考。结对编程也是一个查漏补缺的过程,两个人可以互相看出对方在解题过程中的不足和缺点,可以互相指出和互相学习更正。
第四章重点是找到局部最优,并证明是题目的整体最优选择。难点在于代码实现,相对于解题思路的得出来说。