【算法设计与分析】 最优服务次序问题

算法课程展示 最优服务次序问题

简介
青岛某高校,信安专业,算法课程第三次课堂展示

问题描述

设有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

每个顾客的等待时间,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 因为交换两项对其他项没有影响。

所以T2-T=(b-a)*(t[b]-t[a])

(b-a)>0,(t[b]-t[a])>=0,

(T2-T)>=0
所以对任意两项进行交换都无法使等待时间变得更短,因此贪心策略正确。

代码实现

#include
#include
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)

你可能感兴趣的:(算法,算法,贪心算法)