问题
设有 n 个顾客同时等待⼀项服务。顾客 i 需要的服务时间为 ti (1≤i≤n) 。 应如何安排 n 个顾客的服务次序才能使平均等待时间达到最⼩?平均等待时间 是 n 个顾客等待服务时间的总和除以 n。
示例:
数据输⼊:第⼀⾏是正整数 n,表示有 n 个顾客。接下来的 1 ⾏中,有 n 个正整数,表示 n 个顾客需要的服务时间。
10
56 12 1 99 1000 234 33 55 99 812
结果输出: 计算出的最⼩平均等待时间。
532.00
分析
首先我们看下题目,是要我们安排 n 个顾客的服务次序使平均等待时间达到最⼩。
当解决这个问题时,我们的目标是找到一种安排顾客服务次序的方式,使得平均等待时间最小化。
我们可以使用贪心算法来逐步构建最优解。贪心算法的基本思路是,每次选择当前看起来最优的选择,然后向前推进一步。
在这个问题中,我们可以按照以下步骤来构建最优解:
首先,我们需要将顾客的服务时间进行排序,以便找到最优次序。较短的服务时间应该在前面进行处理,以减少等待时间。
排序后,我们按照服务时间的顺序开始为顾客提供服务。我们从第一个顾客开始,累计当前顾客的服务时间,并将其加到总的等待时间中。
对于下一个顾客,我们将其服务时间加到累计时间中,并将累计时间再次添加到总的等待时间中。我们重复这个过程,直到处理完所有的顾客。
最后,我们计算平均等待时间,将总等待时间除以顾客的数量。
也就是说,我们要让比较快搞定的人排在前面,这样后面的人的等待时间就会更短,通过按照服务时间的顺序处理顾客,可以最大程度地减少等待时间,从而得到了最小的平均等待时间。
代码和运行结果
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> t(n);
for (int i = 0; i < n; i++) {
cin >> t[i];
}
sort(t.begin(), t.end()); // 将服务时间从小到大排序
double avg = 0;
for (int i = 0; i < n; i++) {
avg += (n - i) * t[i]; // 计算平均等待时间,后面的人都要等他服务完了才能轮到他们
}
avg /= n;
printf("%.2f\n", avg); // 保留两位小数输出
return 0;
贪心问题的两个解题思路:
一是短视:只考虑相邻的两个去除哪一个才是最优解,不考虑多个的情况。
二是排序:根据某些关键变量对输入数据进行排序,这其中的关键就是排序标准是什么,可以是某一类输入数据的大小,也可以是某几类输入数据的乘或和。
这道题的关键就是只考虑两个人的情况,让服务时间短的排在前面可以让两个人的等待时间最短,同样的,当人多起来后,我们遍历数组,每次也只考虑相邻的两个人,让服务时间短的排在前面,于是就形成了这道题的贪心策略。