算法设计与分析第四章作业
设有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
问题描述
条件:磁盘空间有限;程序大小不同。
在有限的磁盘上存放尽可能多的程序,就要求选择的程序尽可能小。
算法描述
贪心算法:总是从可选程序中选择最小的试放入磁盘。
-
排序:对程序按大小升序排;
-
循环添加:从i = 1开始,选择排序后序列的第 i 个(即a[i],1 <= i <= n)个加入暂存(sum,初始为0),判断是否满足sum小于磁盘空间,是则计数(count++),否则跳出循环;
反证法证明贪心选择可以推出最优解:
-
证明选择可以从贪心(最小程序)开始:选择从最小程序开始即解不为空时可以选择最小程序。假设解不为空,从这样得到的选择序列中任选一个,用最小程序替换,放入程序数(count)不变;
-
证明最优子结构性质:在解不为空、第一次可以选择最小程序的前提下,假设在最优解中去掉第一次选择的最小程序后得到的子问题的最优解的count_0大于原问题最优解的count_1-1,那么将最小程序加入选择产生的解的count_2大于count_1,此时count_1不是最优解,这不成立。故此问题具有最优子结构性质。
时间和空间复杂度分析
时间复杂度:程序进行了一次快排(O(nlogn))和循环(O(n)),故时间复杂度为O(nlogn);
空间复杂度:程序new了一个一维数组(a[n])用于存放每个程序的大小,故时间复杂度为O(n)。
贪心算法
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
解题的一般步骤
- 建立数学模型来描述问题;
- 把求解的问题分成若干个子问题;
- 对每一子问题求解,得到子问题的局部最优解;
- 把子问题的局部最优解合成原来问题的一个解。
和动态规划有相似之处。最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解,大部分情况下这是不可行的。贪心算法和动态规划本质上是对子问题树的一种修剪,两种算法要求问题都具有的一个性质就是子问题最优性(组成最优解的每一个子问题的解,对于这个子问题本身肯定也是最优的)。动态规划方法代表了这一类问题的一般解法,我们自底向上构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而贪心算法是动态规划方法的一个特例,可以证明每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话说,不需要知道一个节点所有子树的情况,就可以求出这个节点的值。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到底就可以了。