题目描述
设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。程序i存放在磁带上的长度是Li, 1<= i<= n。这n 个程序的读取概率分别是p1,p2,...,pn,且pi+p2+...+pn = 1。如果将这n 个程序按 i1,i2,....,in 的次序存放,则读取程序ir 所需的时间tr=c*(Pi1*Li2+Pi2*Li2+...+Pir*Lir)。这n 个程序的平均读取 时间为t1+t2+...+tn。 磁带最优存储问题要求确定这n 个程序在磁带上的一个存储次序,使平均读取时间达到 最小。试设计一个解此问题的算法,并分析算法的正确性和计算复杂性。 编程任务: 对于给定的n个程序存放在磁带上的长度和读取概率,编程计算n个程序的最优存储方 案。
输入
由文件input.txt给出输入数据。第一行是正整数n,表示文件个数。接下来的n行中,
每行有2 个正整数a 和b,分别表示程序存放在磁带上的长度和读取概率。实际上第k个程
序的读取概率ak/(a1+a2+...+an)。对所有输入均假定c=1。
每行有2 个正整数a 和b,分别表示程序存放在磁带上的长度和读取概率。实际上第k个程
序的读取概率ak/(a1+a2+...+an)。对所有输入均假定c=1。
输出
输出一个实数,保留1位小数,表示计算出的最小平均读取时间。
示例输入
5
71 872
46 452
9 265
73 120
35 87
示例输出
85.6
算法设计
n个程序的平均读取时间:(贪心策略)
在该题目中,要考虑综合因素:长度和读取概率。要求n个程序的平均读取时间最短。按照贪心策略,则每个程序的读取时间都应该最短。故:
(1)计算每个程序的长度和读取概率的乘积。
(2)对(1)产生的结果进行排序。
(3)当访问次序确定时,求出每个程序的访问时间。
(4)求出n个程序的平均读取时间。
程序源代码如下
/*
length[n] 程序长度
length1[n] 每个程序的长度和概率的乘积
gailv[n] 程序的概率
gailv1[n] 程序计算后的概率
sum[n] 读取每个程序所需的时间
*/
# include<stdio.h>
# include<stdlib.h>
# define N 10
//计算每个文件被读取的概率
int calculate(int n,int gailv[n],double gailv1[n])
{
int sum=0;
int i;
for(i=0;i<n;i++)
{
sum+=gailv[i];
}
for(i=0;i<n;i++)
{
gailv1[i]=(double)gailv[i]/sum;
}
return 0;
}
//计算文件和读取概率的乘积
int multiple(int n,double gailv1[n],int length[n],double length1[n])
{
int i;
for(i=0;i<n;i++)
{
length1[i]=((double)gailv1[i])*((double)length[i]);
}
return 0;
}
//对乘积进行排序
int swap(int n,double length1[n])
{
int i,j;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(length1[i]>length1[j])
{
double temp;
temp=length1[i];
length1[i]=length1[j];
length1[j]=temp;
}
}
}
return 0;
}
//读取每个程序所用的时间
int he(int n,double length1[n],double sum[n])
{
int i;
for(i=0;i<n;i++)
{
double t;
t+=length1[i];
sum[i]=t;
}
return 0;
}
//读取所有程序的平均时间
int Min_time(int n,double sum[n])
{
int i;
double min_time=0.0;
for(i=0;i<n;i++)
{
min_time+=sum[i];
}
printf("最小平均读取时间为:\n");
printf("%f\n",min_time);
return 0;
}
int main()
{
int n,i;
int length[N];
int gailv[N];
double gailv1[N];
double length1[N];
double sum[N];
printf("请输入文件的个数:\n");
scanf("%d",&n);
printf("请输入每个文件的长度:\n");
for(i=0;i<n;i++)
{
scanf("%d",&length[i]);
}
printf("请输入每个文件的概率:\n");
for(i=0;i<n;i++)
{
scanf("%d",&gailv[i]);
}
calculate(n,gailv,gailv1);
multiple(n,gailv1,length,length1);
swap(n,length1);
he(n,length1,sum);
Min_time(n,sum);
length[n] 程序长度
length1[n] 每个程序的长度和概率的乘积
gailv[n] 程序的概率
gailv1[n] 程序计算后的概率
sum[n] 读取每个程序所需的时间
*/
# include<stdio.h>
# include<stdlib.h>
# define N 10
//计算每个文件被读取的概率
int calculate(int n,int gailv[n],double gailv1[n])
{
int sum=0;
int i;
for(i=0;i<n;i++)
{
sum+=gailv[i];
}
for(i=0;i<n;i++)
{
gailv1[i]=(double)gailv[i]/sum;
}
return 0;
}
//计算文件和读取概率的乘积
int multiple(int n,double gailv1[n],int length[n],double length1[n])
{
int i;
for(i=0;i<n;i++)
{
length1[i]=((double)gailv1[i])*((double)length[i]);
}
return 0;
}
//对乘积进行排序
int swap(int n,double length1[n])
{
int i,j;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(length1[i]>length1[j])
{
double temp;
temp=length1[i];
length1[i]=length1[j];
length1[j]=temp;
}
}
}
return 0;
}
//读取每个程序所用的时间
int he(int n,double length1[n],double sum[n])
{
int i;
for(i=0;i<n;i++)
{
double t;
t+=length1[i];
sum[i]=t;
}
return 0;
}
//读取所有程序的平均时间
int Min_time(int n,double sum[n])
{
int i;
double min_time=0.0;
for(i=0;i<n;i++)
{
min_time+=sum[i];
}
printf("最小平均读取时间为:\n");
printf("%f\n",min_time);
return 0;
}
int main()
{
int n,i;
int length[N];
int gailv[N];
double gailv1[N];
double length1[N];
double sum[N];
printf("请输入文件的个数:\n");
scanf("%d",&n);
printf("请输入每个文件的长度:\n");
for(i=0;i<n;i++)
{
scanf("%d",&length[i]);
}
printf("请输入每个文件的概率:\n");
for(i=0;i<n;i++)
{
scanf("%d",&gailv[i]);
}
calculate(n,gailv,gailv1);
multiple(n,gailv1,length,length1);
swap(n,length1);
he(n,length1,sum);
Min_time(n,sum);
return 0;
}
程序的运行结果: