算法第四章作业
1.对贪心算法的理解
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。也就是说,不从整体最优上加以考虑,做出的只是在某种意义上的局部最优解 。
贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯。
贪心算法一般按如下步骤进行:
1.建立数学模型来描述问题
2.把求解的问题分成若干个子问题
3.对每个子问题求解,得到子问题的局部最优解
4.把子问题的解局部最优解合成原来解问题的一个解
2.选择题目并说明满足算法性质
4-3 最优合并问题
给定k 个排好序的序列, 用 2 路合并算法将这k 个序列合并成一个序列。 假设所采用的 2 路合并算法合并 2 个长度分别为m和n的序列需要m+n-1 次比较。试设 计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。 为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
输入格式:
第一行有 1 个正整数k,表示有 k个待合并序列。 第二行有 k个正整数,表示 k个待合并序列的长度。
输出格式:
输出最多比较次数和最少比较次数。
输入样例:
在这里给出一组输入。例如:
4
5 12 11 2
输出样例:
在这里给出相应的输出。例如:
78 52
#include<iostream> #include<algorithm> using namespace std; int cmp(int x,int y) { return x>y; } int da(int a[],int k) { int min=0; for(int i=0;i<k-1;i++){ sort(a+i,a+k); a[i+1]+=a[i]; min+=a[i+1]-1; } return min; } int xiao(int b[],int k) { int max=0; for(int i=0;i<k-1;i++){ sort(b+i,b+k,cmp); b[i+1]+=b[i]; max+=b[i+1]-1; } return max; } int main() { int k; int a[100005]; int b[100005]; cin>>k; for(int i=0;i<k;i++){ cin>>a[i]; b[i]=a[i]; } cout<<xiao(b,k)<<" "<<da(a,k)<<endl; }
运用的数学模型:将所得的数据先由小到大排序,而后求最小两个数之和,再将此结果与其他数据再次排序,可得最少比较次数;以此类推,从大到小排序可得出最多比较次数。这样就可以把问题化成每次只求两个数之和,并整体排序。
遇到的问题:在运用贪心算法时,建立数学模型常常是问题的关键,比如在这道题中,我们一开始只认为比较次数与排序有关,因此直接在排好序后从头加到尾直接输出,但在实际运算中,发现有时相比顺序增加,相同的数字先进行相加运算,会得出更少的结果,如“2,2,3,3”,若只按照顺序增加,最后得出的最少次数是18,但如果两个2和两个3分别先相加,最后得出的最少次数是8。因此我们想到,需要在每一次相加运算后再进行一次排序,排出新的最小的两个数。
结对编程情况:两个人更加默契了,解决问题的效率也在提高。