磁带最优存储问题——贪心算法
磁带最优存储问题——贪心算法
问题描述
磁带最优存储问题:设有n个程序{1,2,……n }要存放在长度为L的磁带上。程序i 存放在磁带上的长度是li ,1<=i<= n。这n个程序的读取概率分别为p1,p2,…… pn,且Σpi=1(i=1,2,….n)。如果将这n个程序按i1,i2,…… in的次序存放,则读取程序所需的时间tr=cΣpik lik(k=1,2,….r)(可假定c为1)。这n 个程序的平均读取时间为t(1)+t(2)+...+t(r)。磁带最优存储问题要求确定这n 个程序在磁带上的一个存储次序,使平均读取时间达到最小。
解题思路
此问题采用贪心算法,平均读取时间最小即找到最短读取时间。先计算各程序读取时间并排序,然后计算平均读取时间。
问题难点:
平均读取时间该如何理解?
起初我理解为简单的每个程序的读取时间相加,但如果这样排序便没有了意义,因为此时平均读取时间唯一。
正确理解为:每个程序ti的读取时间 = 自身时间 + 前面所有程序的读取时间, 此时才有了平均读取时间的不同。
程序代码
在理解了平均读取时间这个概念之后,其余的事情便变得简单了。我采用结构体存储,在计算完概率和长度后再进行排序,最后累加结果,一切就迎刃而解了。
点击查看代码
#include<iostream>
#include<algorithm>
using namespace std;
#define M 100
int a[M] = {0};
double Allp = 0;//概率总和
double Mintime = 0.0;
struct ori{
int a;
double b;
double time;
}orii[M];
void probability(ori* a, int n){//计算读取概率
for(int i = 0; i < n; i++){
Allp += a[i].b;
}
for(int i = 0; i < n; i++){
a[i].b = a[i].b / Allp;
}
}
void ptime(ori* a, int n){//计算时间 ! 如何计算最短时间 Ti = 自己加之前
for(int i = 0; i < n; i++){
a[i].time = a[i].a * a[i].b;//单独
}
}
bool cmp(ori a, ori b){
return a.time < b.time;
}
double minTimeCost(ori* a, int n){
probability(a, n);
ptime(a, n);//!
sort(a, a+n, cmp);//排序
// for(int i = 0; i < n; i++){
// Mintime += a[i].time + Mintime;
// }
/*
在如何计算平均读取时间上,我一开始想到加上一个Mintime的值,但单一Mintime属于少加一部分,需要进一步思考。不过,在参考其他人代码后发现,只要两个for循环便能完美解决问题,这一点值得牢记。
更新:找到减少时间复杂度的方法,已添加至文章后半段
*/
for(int i = 0; i < n; i++){
for(int j = 0; j <= i; j++){
Mintime += a[j].time;
}
}
return Mintime;
}
int main(){
int n;
cout << "请输入文件个数:";
cin >> n;
cout << "请输入具体信息:" << endl;
for(int i = 0; i < n; i++){
cin >> orii[i].a >> orii[i].b;
}
cout << "平均最短时间为:" << minTimeCost(orii, n) << endl;
// cout << Allp << endl;
// for(int i = 0; i < n; i++){
// cout << orii[i].a << " " << orii[i].b << " " << orii[i].time;
// cout << endl;
// }
return 0;
}
点击查看代码
//减少时间复杂度
for(int i = 0; i < n; i++){
a[i].time+=a[i-1].time;
}
for(int i = 0; i < n; i++){
Mintime+= a[i].time;
}
--------------------------------------------------------------------------------------------------------
for(int i=0;i<n;i++)
{
sum+=a[i].time*(n-i); //倒序累加 想出这个方法的人是天才吧!
}
输入样例:
71 872
46 452
9 265
73 120
35 85
结果:
平均最短时间为:85.6193

浙公网安备 33010602011771号