算法第四章作业
1.对贪心算法的理解
贪心算法总是做出在当前看来是最好的选择,即贪心算法并不是从整体最优上加以考虑,所做的选择只是在某种意义上的局部最优选择。选择的贪心策略必须具有无后效性,即当前选择的结果必须不能对之前的结果状态产生影响,而只与当前状态有关。一般用贪心算法思想解题的步骤:建立数学模型来描述问题;把求解问题分成若干个子问题;对每一子问题求解,得到子问题的局部最优解;把子问题的局部最优解合成原来解问题的一个解。可以用贪心算法求解的问题中一般有两个重要性质:贪心选择性质(所求问题的整体最优解可以通过一系列局部最优的选择来达到)和最优子结构性质。
2.请选择一道作业题目说明你的算法满足贪心选择性质
4-1 程序存储问题 (90分)
设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。程序i存放在磁带上的长度是 li,1≤i≤n。 程序存储问题要求确定这n 个程序在磁带上的一个存储方案, 使得能够在磁带上存储尽可能多的程序。 对于给定的n个程序存放在磁带上的长度,计算磁带上最多可以存储的程序数。
输入格式:
第一行是2 个正整数,分别表示文件个数n和磁带的长度L。接下来的1行中,有n个正整数,表示程序存放在磁带上的长度。
输出格式:
输出最多可以存储的程序数。
输入样例:
在这里给出一组输入。例如:
6 50
2 3 13 8 80 20
输出样例:
在这里给出相应的输出。例如:
5
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int put(int *a,int n, int L){
sort(a,a+n);
int count=0;
for(int i=0;i<n;i++){
if(L>=a[i]&&i<n){
L-=a[i];
count++;
}
}
return count;
}
int main(){
int n,L;
cin >> n >> L;
int a[10000];
for(int i=0;i<n;i++){
cin >> a[i];
}
cout << put(a,n,L)<< endl;
return 0;
}
贪心选择性质是指,所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
要确定是否具有贪心选择性质,必须证明每步所做的贪心选择最终导致问题的整体最优解。
在该题,即证明该最优解包含程序1。(该题,我的贪心算法思想是,先把磁盘上的程序按长度从小到大排序,然后从长度最小的开始放入磁盘,直至磁盘已满,即可找到最优解)证明:
设A为最优解,并且A中最先放入磁带的程序是程序a。
若a=1,则最优解包含程序1,即A是一个以贪心选择开始的最优解。
若a>1,则表示最优解不包括程序1,令B=A-{a}U{1},因为程序1是最优解,所以其长度小于程序a的长度,并且A中的程序个数和B中的相同,所以B也是一个最优解,而且B中包含程序1,所以总存在以贪心选择开始的最优储存方案。
3.请说明在本章学习过程中遇到的问题及结对编程的情况
本章学习过程中遇到的问题:刚开始学习贪心算法的时候,有道货币找零的题目,一开始我看到题目的时候有想法但打 不出来,就是对贪心算法还不够了解,没有领悟其中的魅力,然后在看书和看PPT回想老师上课讲的内容之后,慢慢就可以把代码打出来了。
结对编程的情况:这一次的上机实验中,在答第一题的时候,我一开始只通过了两个测试点,还有一个(一个都没放的测试点)没通过;我的伙伴一开始也是只通过了两个测试点,还有一个(全部都放的测试点)没通过,然后我们两个人通过讨论自己代码的问题和对于代码,来找出没有通过测试点的地方,在讨论完之后修改自己的代码,然后就都通过了。由此可以感觉到结对编程可以使我在讨论中学习更多一开始被自己忽略掉的内容,可以更好地掌握该知识点,也可以学习他人代码,从而知道自己代码哪里可以改进,使代码简洁易懂。