算法课程展示 最优服务次序问题
简介:
青岛某高校,信安专业,算法课程第三次课堂展示
问题描述
设有n个顾客同时等待一项服务,顾客i需要服务的时间为t[i](1<= i <=n)。应如何安排n个顾客的服务次序才能使平均等待时间达到最小?平均等待时间是n个顾客等待服务时间总和除以n。
问题解释
//输入样例:
10
56 12 1 99 1000 234 33 55 99 812
样例解释:
对于上述样例,如果按照输入顺序进行安排,计算每位顾客的等待时间T(i),T(1)=0,
T(2)=t[1]=56,T(3)=t[1]+t[2]=56+12=68…即每位顾客的等待时间等于前边顾客所需服务时间的总和。
贪心选择策略
每次选取在剩余顾客当中,所需服务时间最短的顾客进行服务。
即将顾客所需的服务时间进行排序,每次选择排序后的第一个顾客进行服务。
贪心策略的证明
本文采取交换论证的证明方法。
交换论证:
假设有一个不同于贪心算法的其他算法,得到的问题的最优解,我们交换其他算法中的某些步骤或者变量,使其成为贪心算法,得到的最优解不会变差。
对本题的证明:
t[i] 表示第i个顾客所需的服务时间,T[i]表示第i个顾客所需的等待时间。
根据贪心策略,当i<j时,t[i]<=t[j](由小到大进行排序)
每个顾客的等待时间,T(1)=0,T(2)=t[1],T(3)=t[1]+t[2],………,T(n)=t[1]+t[2]+…+t[n-1]
所以总的等待时间表示为:T=(n-1)*t[1]+(n-2)*t[2]+…….+t[n-1]+t[n].
取 a,b 两个数满足 1<=a<b<=n,交换上式中的第a项和第b项,此时得到总时间和为T2
因为交换两项对其他项没有影响。
所以T2-T=(b-a)*(t[b]-t[a])
(b-a)>0,(t[b]-t[a])>=0,
(T2-T)>=0
所以对任意两项进行交换都无法使等待时间变得更短,因此贪心策略正确。
代码实现
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int t[N],s[N]; //s为前缀和数组,记录第i个顾客的等待时间
/*
10
56 12 1 99 1000 234 33 55 99 812
*/
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>t[i];
sort(t+1,t+n+1);
for(int i=1;i<=n;i++) s[i]=s[i-1]+t[i];
int res=0;
for(int i=1;i<=n;i++){
res+=s[i];
}
double ans=res*1.0/n*1.0;
cout<<ans;
return 0;
}
时间复杂度分析
借助前缀和优化后的算法,可以在O(1)的时间内求得第i个顾客的等待时间,因此该算法时间复杂度的瓶颈受限制于排序,时间复杂度为O(nlogn)