第四章上机实践报告
一、实践题目
本次实践的题目为4-1程序存储问题
二、问题描述
设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。程序i存放在磁带上的长度是 li,1≤i≤n。 程序存储问题要求确定这n 个程序在磁带上的一个存储方案, 使得能够在磁带上存储尽可能多的程序。 对于给定的n个程序存放在磁带上的长度,计算磁带上最多可以存储的程序数。
简单点说,就是要求我们把相对小的程序存放在磁带上,使磁带上的存储尽可能多的程序。
用数学模型来表示的话就是给出一组数组与一个固定的数字,将数组中的元素相加,得出小于或等于给定的数,要求加数数目最多。
三、算法描述
该算法贪心选择的意义就是使剩余的磁带长度极大化,以便能够放入更多的程序。
按程序的大小按照按非升序进行排列,然后按顺序将程序放到磁带上,每放入一个程序,磁带长度减去程序大小,直到磁带容不下一个完整的程序则结束。
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 int main() 6 { 7 int n; 8 int l; 9 cin >> n; 10 cin >> l; 11 int a[100]; 12 for(int i = 0;i < n;i++) 13 { 14 cin >> a[i]; 15 } 16 sort(a,a + n); 17 int num = 0; 18 for(int i = 0;i < n;i++) 19 { 20 if(l >= a[i]) 21 { 22 num++; 23 l -= a[i]; 24 } 25 else 26 break; 27 } 28 cout << num; 29 system("pause"); 30 return 0; 31 }
设E = {1,2,…,n}为所给的程序集合。由于E中程序按大小的非升序排列,故程序1占用最短的磁带长度。
设A(包含于E)是所给的程序存储问题的一个最优解,且A中程序也程序大小进行非升序排列,A中的第一个活动是k。
若k = 1,则A是一个以贪心选择开始的最优解。
若A > 1,则设B = A – {k} U {1}。由于f1 <= fk,且A中的程序是可放入磁带上的,故B中的程序也是可的放入磁带上的。又由于B中程序个数与A中程序个数相同,且A是最优的,故B也是最优的。也就是说,B是以贪心选择程序1开始的最优程序存储。如果说B不是最优解,那么因为fk >= f1,A也不可能是最优解,与已知相矛盾。
由此可见,总存在以贪心选择开始的最优程序存储方案。
四、算法时间及空间复杂度分析
算法时间复杂度:
算法中使用了C++本身自带的sort函数,其运用的是快速排序,时间复杂度为O(N logN),模拟程序放入磁带的过程时间复杂度为O(N),所以算法的时间复杂度为:O(N logN) + O(N) = O(N logN)
空间复杂度:
同样的道理,算法的空间复杂度与快速排序的空间复杂度相等,同样为O(1)
五、心得体会
这道题相对来说是很简单的,当时它却很好的表现了什么是“贪心算法”,贪心算法就是要尽可能的“贪”,总体上与动态规划相似,都是要取得最优解,但是贪心算法往往是自上而下,得到的就解都是相对于当前的。
虽然比起动态规划,贪心算法的普适性不太高,但是他胜在简便,在二者都适用的情况下,选择贪心算法进行编程会跟方便。