编程之美 1.8小飞的电梯调度算法

题目:

  亚洲微软研究院所在的希格玛大厦一共有6部电梯。在高峰时间,每层都有人上下,电梯每层都停。实习生小飞常常会被每层都停的电梯弄的很不耐烦,于是他提出了这样一个办法:
  由于楼层并不算太高,那么在繁忙的上下班时间,每次电梯从一层往上走时,我们只允许电梯停在其中的某一层。所有乘客从一楼上电梯,到达某层后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层。在一楼的时候,每个乘客选择自己的目的层,电梯则计算出应停的楼层。

问:电梯停在哪一层楼,能够保证这次乘坐电梯的所有乘客爬楼梯的层数之和最少?

 

 

方法一:暴力枚举,时间复杂度O(N^2)

用数组nPerson[i]存放在第i层下楼的人数,在不同的i层停靠,求所有人需要走的楼层总和,找出总和最小的楼层Target,输出。用两重循环完成计算。

 1 /*
 2 * 1.8.1
 3 *
 4 *  Created on: Jan 9, 2016
 5 *      Author: SeekHit
 6 */
 7 #include "iostream"
 8 #define N 100
 9 
10 using namespace std;
11 
12 int func(int n, int nPerson[]){
13 
14     int nFloor, nMinFloor=0, TargetFloor=0;
15 
16     for (int i = 1; i <= n; i++){
17         nFloor = 0;
18         for (int j = 1; j<i; j++)
19             nFloor += (i - j)*nPerson[j];
20         for (int j = i + 1; j <= n; j++)
21             nFloor += (j - i)*nPerson[j];
22 
23         if (TargetFloor==0||nMinFloor>nFloor){    //如果没有TargetFloor==0,nMinFloor>nFloor始终无法满足,不执行if里面的内容 
24             nMinFloor = nFloor;
25             TargetFloor = i;
26 
27         }
28     }
29     return TargetFloor;
30 }
31 
32 int main(){
33     int n, Target;
34     int nPerson[N];
35     cout<<"输入楼层总数n:"<<endl;
36     cin>>n;
37     cout<<"输入每层楼下的人数"<<endl;
38     for (int i = 1; i <= n; i++){
39         cout<<""<<i<<"层下的人数:"<<endl;
40         cin>>nPerson[i]; 
41     }
42 
43     Target = func(n, nPerson);
44     cout<<"电梯停靠最优层数为:"<<Target<<endl;
45 }

 

方法二:时间复杂度为O(N)的动态规划的算法

降低时间复杂度,求解。假设停在i层,可以计算出所有乘客需要爬的楼层总数Y。设N1个人在i层以下下楼,N2个人在i层下楼,N3个人在i层以上下楼。

如果现在电梯改在i-1层停靠,现在所有i层和i层以上的都要多走一楼,相当于,总共多爬了N2+N3层,而i层以下的所有人少爬了一楼,就是少了N1层。总数变成了N2+N3-N1层,如果N2+N3-N1<Y,说明降一层停靠更优。

反之,如果i+1层停靠,所有乘客爬的楼层数变成了N1+N2-N3,如果N1+N2-N3<Y说明升一层停靠更优。

书上给的程序就是用升楼的方式来判断的,也可以用降楼来动态规划最优楼层数。

 1 /*
 2 * 1.8.2动态规划 
 3 *
 4 *  Created on: Jan 9, 2016
 5 *      Author: SeekHit
 6 */
 7 #include "iostream"
 8 #define N 100
 9 
10 using namespace std;
11 
12 int func(int n, int nPerson[]){
13 
14     int nMinFloor=0, TargetFloor=1;
15     int N1=0,N2=nPerson[1],N3=0;
16 
17 //计算N3,就停靠在1楼时,需要走的总楼层数 
18     for (int i = 2; i <= n; i++){
19         N3+=nPerson[i];
20         nMinFloor+=nPerson[i]*(i-1);
21     }
22     
23     for(int i=2;i<=n;i++){
24         if(N1+N2<N3){
25             TargetFloor=i;
26             nMinFloor+=(N1+N2-N3);
27             N1+=N2;
28             N2+=nPerson[i];
29             N3-=nPerson[i]; 
30         }
31         else
32             break;
33     }
34     return TargetFloor;
35 }
36 
37 int main(){
38     int n, Target;
39     int nPerson[N];
40     cout<<"输入楼层总数n:"<<endl;
41     cin>>n;
42     cout<<"输入每层楼下的人数"<<endl;
43     for (int i = 1; i <= n; i++){
44         cout<<""<<i<<"层下的人数:"<<endl;
45         cin>>nPerson[i]; 
46     }
47 
48     Target = func(n, nPerson);
49     cout<<"电梯停靠最优层数为:"<<Target<<endl;
50 }

运行结果:

 

扩展问题:

往上爬比往下走要累,往上爬一层消耗k个单位的能量,往下走只消耗1个单位的能量,求让所有人消耗的能量最少。

解法:

只需将计算N1+N2-N3变成N1+N2-N3*K即可。其余的都一样。

posted @ 2016-01-09 16:56  SeeKHit  阅读(565)  评论(0编辑  收藏  举报