贪心之最优服务次序问题

来源:互联网 发布:js表单验证代码大全 编辑:程序博客网 时间:2024/05/17 22:27

最优服务次序问题

一、问题描述: 
   设有n个顾客同时等待一项服务。顾客i需要的服务时间为ti, 1≦i ≦n 。共有s处可以提供此服务。应如何安排n个顾客的服务次序才能使平均等待时间达到最小?平均等待时间是n 个顾客等待服务时间的总和除以n。

二、贪心选择策略 
假设原问题为T(先假设只有一个服务点),而我们已经知道了某个最优服务系列,即最优解为 
A={t(1),t(2),….t(n)} 
(其中t(i)为第i个用户需要的服务时间),则每个用户等待时间为: 
T(1)=t(1);T(2)=t(1)+t(2);...T(n)=t(1)+t(2)+t(3)+…+t(n);

那么总等待时问,即最优值为: 
TA=T(1)+T(2)+T(3)+...+T(n)=n*t(1)+(n-1)*t(2)+…+(n+1-j)*t(i)+…+2*t(n-1)+t(n);

由于平均等待时间是n个顾客等待时间的总和除以n,故本题实际上就是求使顾客等待时间的总和最小的服务次序。

本问题采用贪心算法求解,贪心策略如下: 
  对服务时间最短的顾客先服务的贪心选择策略。首先对需要服务时间最短的顾客进行服务,即做完第一次选择后,原问题T变成了需对n-1个顾客服务的新问题T'。新问题和原问题相同,只是问题规模由n减小为n-1。基于此种选择策略,对新问题T',选择n-1顾客中选择服务时间最短的先进行服务,如此进行下去,直至所有服务都完成为止 。

三、问题的贪心选择性质 
   先来证明该问题具有贪心选择性质,即最优服务A中t(1)满足条件:t(1)<=t(i)(2<i<n)。 

用反证法来证明:假设t(1)不是最小的,不妨设t(1)>t(i)(i>1)。 
设另一服务序列B=(t(i),t(2),…,t(1)…,t(n)) 
那么TA-TB=n*[t(1)-t(i)]+(n+1-i)[t(i)-t(1)]=(1-i)*[t(i)-t(1)]>0 
即TA>TB,这与A是最优服务相矛盾。 
故最优服务次序问题满足贪心选择性质。

四、问题的最优子结构性质 
   在进行了贪心选择后,原问题T就变成了如何安排剩余的n-1个顾客的服务次序的问题T',是原问题的子问题。 
若A是原问题T的最优解,则A'={t(2),…t(i)…t(n))是服务次序问题子问题T'的最优解。 

证明:假设A'不是子问题T'的最优解,其子问题的最优解为B',则有TB'<TA',
而根据TA的定义知,TA'十t(1)=TA。因此TB'+t(1)<TA'+t(1)=TA, 
即存在一个比最优值TA更短的总等待时间,而这与TA为问题T的最优值相矛盾。因此,A'是子问题T'的最优值。

从以上贪心选择及最优子结构性质的证明,可知对最优服务次序问题用贪心算法可求得最优解。

根据以上证明,最优服务次序问题可以用最短服务时间优先的贪心选择可以达到最优解。 
故只需对所有服务先按服务时间从小到大进行排序,然后按照排序结果依次进行服务即可。平均等待时间即为TA/n。

五、算法实现 
    由多处最优服务次序问题具有贪心选择性质和最优子结构性质,容易证明算法greedy的正确性。本算法采用最短服务时间优先的贪心策略。首先将每个顾客所需要的服务时间从小到大排序。然后申请2个数组: 
st[]是服务数组,st[j]为第j个队列上的某一个顾客的等待时间;su[]是求和数组,su[j]的值为第j个队列上所有顾客的等待时间;


[cpp] view plain copy
  1. #include<iostream>   
  2. #include <vector>   
  3. #include<algorithm>    
  4. using namespace std;   
  5. using std::vector;   
  6.   
  7. double greedy(vector<int>x,int s)   
  8. {   
  9.     vector<int>st(s+1,0);  
  10.     vector<int>su(s+1,0);    
  11.     int n=x.size();    
  12.     sort(x.begin(),x.end());    
  13.     int i=0,j=0;    
  14.       
  15.     while(i<n){  
  16.         st[j]+=x[i];     
  17.         su[j]+=st[j];     
  18.         i++;  
  19.         j++;     
  20.         if(j==s)j=0;   
  21.     }   
  22.   
  23.     double t=0;  
  24.   
  25.     for(i=0;i<s;i++)   
  26.         t+=su[i];   
  27.     t/=n;   
  28.     return t;  
  29. }    
  30.   
  31. void  main()  
  32. {  
  33.     int n;//等待服务的顾客人数    
  34.     int s;//服务点的个数    
  35.     int i;    
  36.     int a;     
  37.     int t;//平均服务时间    
  38.     vector<int>x;     
  39.     cout<<"please input the num of the customer:"<<endl;    
  40.     cin>>n;     
  41.     cout<<"please input the num of the server:"<<endl;    
  42.     cin>>s;     
  43.     cout<<"please input the need service time of each customer:"<<endl;    
  44.   
  45.     for(i=1;i<=n;i++)  
  46.     {  
  47.         cout<<"No."<<i<<endl;   cin>>a;   x.push_back(a);   
  48.    }   
  49.    t=greedy(x, s);   
  50.    cout<<"the least average waiting time is:"<<t<<endl;   
  51. }  
0 0
原创粉丝点击