问题一题目描述
根据输入的程序读取概率和放在磁带上的长度计算出最小的平均读取时间。
题目分析
我们首先将输入的所有读取概率加和作为求小数概率的分母,最后求出对应概率乘以放在磁带上的长度,才得到了一个程序的读取时间。最后按照一定顺序排列这些文件的读取时间求出最小的平均读取时间。
这是一个典型的贪心法的问题,因为后面读取的文件要等待前面读取的文件读完,所以我们应该把读取时间较短的文件排在前面,否则后面的短文件要等待很久。这就像我们操作系统中的SJF(最短任务优先策略)。
每次读入前一个程序的时候要一直加上之前的等待时间,最终这些值都加在一起就是我们最终的最小平均读取时间。
代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
int main()
{
int n;//程序数目
cin>>n;
double l,p;
double sum_p = 0;
vector<double>tr;
vector<double>pr;
vector<double>lr;
double res = 0;
for(int i = 0;i < n;i++)
{
cin>>l>>p;
lr.push_back(l);
pr.push_back(p);
sum_p += p;
}
for(int i = 0;i < n;i++)
{
tr.push_back((pr[i] / sum_p) * lr[i]);
}
sort(tr.begin(),tr.end());
double time = tr[0];
for(int i = 1;i < n;i++)
{
res += time;
time += tr[i];
}
//最后一个任务的处理时间没有被读入,我们需要单独拿出来进行加和。
res += time;
cout<<setiosflags(ios::fixed)<<setprecision(4)<<res;
return 0;
}
问题二问题描述
求出最优的服务次序以及最短的服务时间。
题目分析
两个题目之所以放在一起来写,是因为两个问题其实是一模一样的。只不过这个问题不需要我们去处理一些数据而已。但是都是采用贪心法的SJF,最短任务有限策略。需要被服务时间少的顾客一定要放在前面,否则需要等待很长时间。
代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
int main()
{
double n;
cin>>n;//等待的顾客人数
vector<int>wait;
int wait_time;
while(cin>>wait_time)
{
wait.push_back(wait_time);
if(cin.get() == '\n')
break;
}
sort(wait.begin(),wait.end());
int time = 0;
double sum = 0;
for(int i = 0;i < wait.size();i++)
{
sum += time;
time += wait[i];
}
//最后一个顾客的服务时间我们没有处理,需要单独拿出来处理
sum += time;
cout<<setiosflags(ios::fixed)<<setprecision(2)<<sum / n;
return 0;
}
总结
当我们想要获取最短的时间消耗或者最优的服务次序时,就要想到贪心法的SJF策略。我们只需要遍历一遍我们的存取时间消耗的数组,便可以找出这个最优次序。如果想要拿到实际的次序,只需要在排序算法中将对应任务的索引也进行交换即可。或者直接声明一个结构体,统一进行排序操作。