第四章作业
一.贪心算法概念理解:
在对问题求解时,总是做出在当前看来是最好的选择。它不要求考虑问题整体,仅仅保证每次的求解步骤是当前最优解。
所以贪心算法具有局限性,需要满足最优子结构性质和局部最优产生全局最优的性质才能使用贪心算法,并不是所有问题都能使用贪心算法/找到贪心策略。
贪心策略是贪心算法的关键,只有正确的贪心策略才能得到正确结果,并且某些问题的贪心策略可能不止一个。
二.作业题目举例------最优合并问题
1.问题描述:给定k 个排好序的序列, 用 2 路合并算法将这k 个序列合并成一个序列。
所采用的 2 路合并算法合并 2 个长度分别为m和n的序列需要m+n-1 次比较。
设计算法确定合并这个序列的最优和最差合并顺序,使所需的总比较次数最少和最多。
2.样例分析:

78合并顺序:12+11--23 (12+11) +5--28 (23+5) +2
52合并顺序:2+5--7(2+5)+11--18(7+11)+12
不难发现最差合并顺序是优先选择最长的两个序列合并,最好的合并顺序是优先选择最短的两个序列合并。
3.贪心策略:
最差合并顺序:优先选择最长的两个序列合并,因为可以使最长的序列比较最多次,进而产生最多的比较次数。
每次选择最长两个序列合并正得到最多的比较次数是这一步的局部最优解,而该问题的局部最优产生全局最优解。
最好合并顺序:优先选择最短的两个序列合并,因为可以使最短的序列比较最少次,进而产生最少的比较次数。
每次选择最短两个序列合并正得到最少的比较次数是这一步的局部最优解,而该问题的局部最优产生全局最优解。
4.代码实现:
#include<bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; int m[n],m0[n]; for(int i=0;i<n;i++){ cin>>m[i]; m0[i]=m[i]; } sort(m,m+n); sort(m0,m0+n,greater<int>()); //sort函数的升序排序 int minn=0,maxx=0; for(int i=0;i<n-1;i++){ minn+=(m[i]+m[i+1]-1); m[i+1]+=m[i]; sort(m+i+1,m+n); //每次把合并后的长度赋值给后一位,并且对前面的序列长度不进行排序 } for(int i=0;i<n-1;i++){ maxx+=(m0[i]+m0[i+1]-1); m0[i+1]+=m0[i]; sort(m+i+1,m+n,greater<int>()); } cout<<maxx<<" "<<minn<<endl; return 0; }
三.本章疑难问题
1.贪心策略的选择:
在解决删数问题的时候,没有找到正确的贪心策略导致不知道为什么答案错误,一直在调试错误,却没有发现算法设计就是错的。
所以贪心策略的选择至关重要,在敲代码之前一定要确保贪心策略的正确。
2.贪心策略的实现:
在最优合并问题中,选取最短的两个序列合并是很显然的,但是苦于没有较好的实现方法,去将合并后的序列长度和单个序列长度一起比较。
四.结对编程情况
读题之后,一起讨论贪心策略,并探讨其正确性,下课后会一起交流刚才程序的问题。
我主要负责打代码,队友负责研究算法。

浙公网安备 33010602011771号