一座大厦,里面的电梯一开始在高峰时段每层都停,现设计一种方式,让电梯只停在其中的某一层。所有的乘客从这层爬楼梯到自己的楼层。在一楼的时候,每个乘客选择自己的目的层,电梯自动计算出应该停的层。
问:电梯停在哪一层,能够保证乘坐的所有乘客爬楼梯的层数之和最少。
首先对问题进行抽象->假设楼层共N层,电梯停在第i层,要去第j层的乘客数目总数为nPerson[j],这样,所爬楼梯的总数就是
- Σ{nPerson[j]*|i-j|},j从1到N
###一,暴力求解
从第一层开始,依次算每层的爬楼梯总数。一个嵌套循环。
1 | public class BOP_1_8_elevator { |
###二,找数学规律
- 假设停在第i层,此时总的爬楼层数为Y = Σ{nPerson[j]*|i-j|},j从1到N。
如果有N1个乘客在i层以下,N2个乘客在i层,N3个乘客在i层以上,那么
- 若停在第i-1层,i层及以上都加一层,即N2 + N3, i层以下都减一层,共减去N1,故所有人总共需要爬Y - N1 + N2 + N3
- 若停在第i+1层,i层及以下都加一层,即N1 + N2, i层以上都减一层,共减去N3,故所有人总共需要爬Y + N1 + N2 - N3
因而
- 当N2 + N3 - N1 > 0 时,停在i-1更好,即N2 > N1 - N3
- 当N2 + N1 - N3 < 0 时,停在i+1更好,即N2 < N3 - N1
- 其他情况在i
所以,从第一层开始的话,必定有一个N2 + N1 - N3 = 0 的时刻,此时的i即为要求的i。
1 | private static int[] getRes2(int[] nPerson, int N) { |
###三,中间数的方法
当有两个人,第一个人在第2层下,第二个人在第9层下,那在2~9中间无论哪个都可以!总共要爬的楼层一定是7层!!若nPerson是{2,1,0,0,2,2},等同于去掉一个最高层和最低层的{1,1,0,0,2,1}的结果,!
过程如下:
* {0,2,1,1,4,2,2}
* {0,1,1,1,4,2,1}
* {0,0,1,1,4,2,0}
* {0,0,0,1,4,1,0}
* {0,0,0,0,4,0,0} 得到应该停在第4层
1 | private static int[] getRes3(int[] nPerson, int N) { |
###扩展,最小能量
若往上走耗费k单位能量,往下走耗费1单位能量,那如何解决。
只需要将公式稍微变一下就好。
- 若停在第i-1层,所有人总共需要爬 Y - N1 + (N2 + n3) * k
- 若停在第i+1层,所有人总共需要爬 Y + N1 + N2 - N3 * k
###扩展,可以停k个楼层
to be continue…