磁带最优存储问题——贪心算法

磁带最优存储问题——贪心算法

问题描述

磁带最优存储问题:设有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

posted @ 2021-11-13 13:58  笨拙的向前  阅读(524)  评论(0)    收藏  举报