转:小飞的电梯调度算法

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

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

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

 

 1 /* 
 2  * O(N^2) 
 3  */  
 4 int N;  
 5 int nPerson[N+1];  
 6 int target_floor;  
 7 int min_floors = INT_MAX;  
 8   
 9 for(i = 1;i<=N;i++)  
10 {  
11     int sum_floors = 0;  
12     for(j = 1;j<=N;j++)  
13     {  
14         sum_floors += nPerson[j] * abs(j - i);  
15     }  
16     if(sum_floors < min_floors)  
17     {  
18         min_floors = sum_floors;  
19         target_floor = i;  
20     }  
21     return (target_floor);  
22 }  

方法二:书上提供的O(N)的动态规划的算法。

假设电梯停在i层楼,可以计算出所有乘客要爬楼层的层数为Y,假设此时有N1个乘客在i层楼以下,N2个乘客在I层楼,N3个乘客在I层楼以上,则当电梯停在i+1层的时候,N1+N2个乘客要多下一层楼,共多下N1+N2层,N3个乘客要少往上面爬一层楼,少上N3层楼,此时Y(i+1) = Y(i) + N1+N2-N3,很显然,当N1+N2<N3的时候,Y不断减小。Y1很容易算出来,另外我们还可以看出,N1+N2是递增的,N3是递减的,所以N1+N2一旦大于N3的时候,我们直接退出循环即可,没有必要再计算下去了。

 1 void LIFT_SCHEDUL1()
 2 {
 3     int i, NUM = 9;
 4     int nPerson[] = {0, 2, 3, 5, 5, 6, 7, 8, 8, 9};   //nPerson[i]表示到第i层的乘客数目
 5     int nMinFloor, nTargetFloor;
 6     int N1, N2, N3;
 7 
 8     nTargetFloor = 1;
 9     nMinFloor = 0;
10     for(N1 = 0, N2 = nPerson[1], N3 = 0, i = 2; i <= NUM; i++)
11     {
12         nMinFloor += nPerson[i] * (i - 1);
13         N3 += nPerson[i];
14     }
15     for(i = 2; i <= NUM; i++)
16     {
17         if(N3 > (N1 + N2))
18         {
19             nTargetFloor = i;
20             nMinFloor += (N1 + N2 - N3);
21             N1 += N2;
22             N2 = nPerson[i];
23             N3 -= nPerson[i];
24         }
25         else break;    
26     }
27 
28     printf("Lift stopped at %d floor is best!\nThe least steps is %d!\n", nTargetFloor, nMinFloor);
29 }
 

方法三:中位数

其实这道题目仔细分析起来就是求一组数据的中位数而已。假设两人,分别到3层楼和8层楼下,在3和8之间取一点,使得到两个点距离最小,很显然,在3和8中的每一点到3和8的距离之和都是相等的。推广到2 3 5 5 6 7 8 8 9这样一组数据,target_floor为中位数。

 1 void LIFT_SCHEDUL2()
 2 {
 3     int NUM = 9;
 4     int nPerson[] = {0, 2, 3, 5, 5, 6, 7, 8, 8, 9};   //nPerson[i]表示到第i层的乘客数目
 5     int left = 1, right = NUM;
 6     while(left < right)
 7     {
 8         while(nPerson[left] == 0) left++;
 9         nPerson[left]--;
10         while(nPerson[right] == 0) right--;
11         nPerson[right]--;
12     }
13     printf("Lift stopped at %d floor is best!\n", left);
14

转自:http://blog.csdn.net/lonelycatcher/article/details/7910877

扩展问题,往上爬一层要耗费K个单位的能量,往下走耗费1个单位的能亮,只需要计算N1+N2-N3变成N1+N2-N3*K即可。其余的都是一样的。

posted @ 2013-04-11 20:06  ggbailei  阅读(208)  评论(0)    收藏  举报