小飞的电梯调度算法

一、问题

亚洲微软研究院所在的希格玛大厦一共有6部电梯。在高峰时间,每层都有人上下,电梯每层都停。实习生小飞常常会被每层都停的电梯弄的很不耐烦,于是他提出了这样一个办法:

由于楼层并不算太高,那么在繁忙的上下班时间,每次电梯从一层往上走时,我们只允许电梯停在其中的某一层。所有乘客从一楼上电梯,到达某层后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层。在一楼的时候,每个乘客选择自己的目的层,电梯则计算出应停的楼层。

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

二、分析

照例,我们先把问题进行数学化,假设我们的楼层总共有N层,电梯停在第x层,要去第i层的乘客数目总数为 Tot[i],这样,所爬楼梯的总数就是
因此,我们要找的就是一个整数x,使得上面的那个式子最小。

三、解法一

当然,我们脑子里最简答的想法还是一个暴力解法,怎么算,一层一层试着来呗,如果电梯停在第一层,所有的乘客一共需要爬多少层,如果电梯停在第二层,所有的乘客一共需要爬多少层。。。。。等等,把所有的层数都试过来之后,找出那个需要的爬的总数最小的那个层数。
代码就不贴了,很简单。

四、解法二

接下来是重头戏了,我们来思考下,还有没有更好的方法呢,更低的时间复杂度呢?
我们这样思考,假设我们把电梯停在第i层,显然我们可以计算出所有的乘客总共需要爬的层数Y,那么假如我们再把电梯停在第i-1层呢?i层以下的乘客是不是就可以少爬一层了,i层以上的呢?是不是就需要多爬一层了呢?第i层的呢?是不是就也同样需要多爬一层了?
根据以上的思考,我们来算一下,如果有N1个乘客的目的楼层在第i层以下,有N2个乘客在第i层,有N3个乘客的目的楼层在第i层以上。假如我们把原来的电梯停在第i层换成停在第i-1层,那么第i层的乘客和第i层以上的乘客需要多爬了一层,总共需要多爬N2+N3层,i层以下的呢?就可以少爬一层,总共需要少爬N1层,那么一共需要爬
Y-N1+N2+N3。同理,如果我们把电梯停在i+1层,一共需要爬Y+N1+N2-N3层,那么也就是说如果:
N1>N2+N3,就是代表我们把电梯停在i-1比较好,同理如果N3>N1+N2,就代表我们把电梯停在i+1比较好。
根据这个规律一层一层考察,计算各位乘客需要爬楼梯的数目。然后在根据上面的策略进行调整,直到找到最佳楼层。这时总的时间复杂度为O(N)
接下来是我自己的思考:
其实书上的代码,我看了之后又一个疑问,代码中给出的意思就是说,当我们从第一层开始调整的时候,一旦发现再往上加一层的话就会使得乘客总的爬楼梯的层数变高,就代表当前层是最好的,但是我心里的疑问是,为什么?为什么不再往上调两层看看是不是最好的。
这个道理其实很简单,但是我还是自己证明了一下,还是刚才上面的例子,加入我们往上调了一层之后,发现乘客需要爬电梯的总数增多了,代表什么?就是说N3<N1+N2,那么假设我们的第i+1层的乘客数目为a个,第i+2层为b个,如果我们把停的电梯放在第i+2层,N3会怎么着?当然变小了,N3指的是停着的那一层上面的乘客数目,那么N1+N2呢,肯定变大,为什么,总数不变N3变小了,指定N1+N2就变大了呗,那么N3<N1+N2,同理你再往上调都是不行的。
代码我还是在网上找一个吧,很简单。
int N;  
int nPerson(N+1);  
int target_floor = 1;  
int min_floors = 0;  
int N1 = 0,N2 = nPerson[1],N3 = 0;  
for(i = 2;i<=N;i++)  
{  
    min_floors += nPerson[i] * (i-1);  
    N3 +=nPerson[i];  
}  
  
for(i = 2;i<=N;i++)  
{  
    if(N1+N2 < N3)  
    {  
        target_floor = i;  
        min_floors +=(N1+N2-N3);  
  
        N1 +=N2;  
        N2 = nPerson[i];  
        N3 -=nPerson[i];  
    }  
    else  
        break;  
}  
return target_floor;  
五、扩展问题
1. 往上爬楼梯,总是比往下走要累的。假设往上爬一个楼层,要耗费k单位的能量,往下走只需要耗费1单位的能量,那么如果题目条件改为让所有人消耗的能量最少,这个问题怎么解决。
这个问题很简单,就是在计算所需能量的时候上楼梯的时候乘以k,下楼梯乘以1就行,方法还是和解法二一个道理。
2. 在一个高楼里面,电梯只在某一个楼层停,这个政策还是不太人性化。如果电梯会在k个楼层停呢?
此问题,作为遗留问题吧,现在时间有点紧迫。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值