算法第四次实践报告
一、实践题目
设有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
二、问题描述
有n个文件,还有一个长度为L的磁带,要将文件存入磁带中,并且要求存放最多的程序,第一行输入的是文件数n及磁带长度,第二行输入的是每个程序的长度。
解题思路:为了存放更多的程序,所以应该将长度小的程序优先存入磁带,根据文件数设置大小为n的数组,存放个文件的程序长度,然后将他们按升序排列,一个个存放入磁带,长度为L的磁带,每次存入一个
程序则减去相对应的长度,设置一个计数器count置0,每次存入则count++,然后判断下一个将存放进去的程序长度是否小于剩余磁带长度,如果满足则继续存放并且减去相对应长度,一直循环到下一个将要
存储的程序超过剩余磁带,则输出次数count。如若文件数全部存放完时依然有剩余空间,则直接输出文件数n。
三、算法描述
#include<iostream> #include<algorithm> using namespace std; int main(){ int n,w; cin>>n>>w; int sum=0; int a[10000]; for(int i=0;i<n;i++){ cin>>a[i]; } sort(a, a+n); for(int i=0;i<n;i++){ sum+=a[i]; if(sum>w){ cout<<i<<endl; return 0 ; } } cout<<n; return 0; }
1.贪心策略:每次都将长度最小的程序优先放入磁带。
2.利用反证法证明贪心选择及最优子结构:
设E={1,2,...,n}为所给的程序集合。由于E中程序按长度大小的非减序排列,故程序1具有最短长度。首先证明程序存储问题有一个最优解以贪心选择开始,即该最优解中包含程序1。设AE是所给的程序存储问题的一个最优解,且A中程序也按长度大小非减序排列,A中的第一个程序是程序k。若k=1,则A就是一个以贪心选择开始的最优解。若k1,则设B=A-{k}∪{1}。由于f1≤fk,则A中程序是相容的,故B中的程序也是相容的。又由于B中程序个数与A中程序个数相同,且A是最优的,故B也是最优的。也就是说,B是以贪心选择程序1开始的最优程序存储。由此可见,总存在以贪心选择开始的最优程序存储方案。
四、算法时间空间复杂度
时间复杂度:O(N);用了一个for循环来依次存放最短程序。
空间复杂度:O(1);没有额外申请空间。
五、心得体会
本次上机实践针对贪心算法的问题,从刚刚开始的只懂一点点理论,到实际实现代码时,有一个很明显的提升,对于贪心算法,可以跟简单的实现代码,理解问题的关键,如何实现贪心策略,结对编程的情况下跟能让自己理解各个问题的关键所在,互相商量讨论之后,可以得出贪心策略,然后一步步实现自己得贪心算法,对于贪心算法,总是寻找最快最短最容易满足得条件来实现就能满足贪心算法得条件。