编程之美 1.8小飞的电梯调度算法
问题:由于楼层并不高,在繁忙时段,每次电梯从一层往上走时,我们只允许停到其中某一层。所有乘客再从这层去往自己的目的楼层。
电梯停在哪一层,能够保证乘客爬楼梯之和最少?
解法一:
枚举停在第i层的情况,计算当停在第i层时所爬楼梯数为nFloor,取其最小值nMinFloor,时间复杂度O(N^2)
解法二:
有没有方法可以通过已知第i层的nFloor,推算出第i+1层的nFloor呢?
设N1为第i层以下的乘客数,N2为第i层的乘客数,N3为第i层以上的乘客数,已知乘客在第i层的nFloor值为Y
如果电梯改停在i-1层时,那么此时nFloor值为Y-N1+(N2+N3)
如果电梯改停在i+1层时,此时nFloor值为Y-N3+(N1+N2)
由此可见N1+N2<N3时,停i+1层更好,这样我们先计算第一层时的N1、N2、N3的值,按照上述规则遍历一次即可得出 nMinFloor 和 nTargetFloor。
这样时间复杂度就降为O(N)。
#include <iostream> using namespace std; const int MAXN=2; int nPerson[MAXN+1]={-1,7,3}; //nPerson[i]表示第i层乘客数 int nFloor,nMinFloor,nTargetFloor; //O(N^2) void dispatching1(int N) { nTargetFloor=-1; for (int i=1;i<=N;++i) { nFloor=0; int j; for(j=1;j<i;++j) nFloor+=nPerson[j]* (i-j);//i层以下 for(j=i+1;j<=N;++j) nFloor+=nPerson[j]*(j-i);//i层以上 if(nTargetFloor == -1 || nMinFloor > nFloor) { nMinFloor = nFloor; nTargetFloor =i; } } } //O(N) int N1,N2,N3; void dispatching2(int N) { nTargetFloor=1; nMinFloor=0; int i; for(N1=0,N2=nPerson[1],N3=0,i=2;i<=N;++i) { N3+= nPerson[i]; nMinFloor+=nPerson[i]*(i-1); } for (i=2;i<=N;++i) { if (N1+N2<N3) { nTargetFloor=i; nMinFloor+=(N1 + N2 -N3); N1 +=N2; N2 =nPerson[i]; N3 -=nPerson[i]; } else break; } } void main() { dispatching1(MAXN); //dispatching2(MAXN); cout<<"TargetFloor:"<<nTargetFloor<<endl; cout<<"MinFloor:"<<nMinFloor<<endl; }