趣味算法题-电梯调度问题

绝世美人儿
815次浏览
2020年09月29日 07:46
最佳经验
本文由作者推荐

六安毛坦厂中学-上海财经大学本科招生网

2020年9月29日发(作者:骆指挥)


趣味算法题-电梯调度问题

这是《编程之美》中的一道题,刚开始 题目比较简单,
但是逐步推进之后的问题也有些难度,这样由简单到难的一
步步深入的思想比较 值得学习。
最初的问题
假如电梯在高峰期间只允许在某一层停留,所有的乘客在一
楼上电梯,到达某层后,所有乘客从电梯下来,到达自己要
去的楼层,在一楼的时候所有乘客选出自己要 去的楼层,电
梯根据所有乘客选择的楼层信息得出要停留的楼层。

那么,电梯停留在那一层,能够保证这次乘坐电梯的所有乘
客爬楼梯的层数之和最少。
问题的分析和解法
该问题本质上是一个优化问题,首先为则个问题找到一个合
适的抽 象模型。从问题中可以看出,有两个因素会影响到最
后的结构:乘客的数目即需要停留的楼层,因此,我 们可以
从统计到达各层的乘客数目开始分析。

假设楼层总共有N层,电梯停留在 X层,要去第i层的乘客
总数目是Tot[i],这样,所爬楼梯的总数就可以表示出老。


因此,我们就是要找到一个整数X使得这个总数的值最小。
解法
首 先思考简单解法,可以从第1层开始枚举X一直到第N
层,然后再计算出如果电梯在第X层的话,所有乘 客总共需
要爬多少层楼。这是最为直接的一个解法。可以看出,这个
算法需要两重循环来完成计 算
int n=0;这个表示电梯所在的最高楼层
int nPerson[] = new int[n+1];这个数组表示要去每
一层的乘客数
上面的两个变量应该是给出的,这里只是示意代
码没有初始化。
int n Floor,nMinFloor,nTargetFloor;分别表示电梯停
在第n层时候的结果, 目前为止的最小结果,最小结果所停
的楼层。
nTargetFloor = -1;考虑到初始化最小结果和最小结
果所砸的楼层,所以先设定为一个非法值
循环遍历每个楼层的结果,算出本层的结果,如
果比之前结果小,就替换之前结果
for(int i = 1; i <= n; i++){
nFloor = 0;
计算本层以下的楼层的人的总消耗
for(int j =1; j < i; j++){


nFloor += nPerson[j]*(i-j);
}
计算本层以上的楼层的人的总消耗
for(int j = i+1; j nFloor){
nMinFloor = nFloor;
nTargetFloor = i
}
}2
这个基本解法的时间复杂度为O(N2)
解法的优化
我们希望尽可能地减少算法的时间复杂度。那么,是否有可
能在低于O(N2)

的规则下求出这个问题的解呢?

我们可以有如下的思路:

假设电梯停在第i层,显然我们可以计算出所有乘客总共要
爬楼梯的层数Y。如果有N1个乘客目的楼 层在第i层楼一
下,有N2个乘客在第i层楼,还有N3个乘客在第i层以上。
这个时候,如果 电梯改停在第i-1层,所有目的地在第i-1层
一下的蹭课可以少爬一层,总共可以少爬N1层,所有 目的


地在i层及以上的乘客都需要多爬1层,总共需要多爬N2+N3
层。因此 ,乘客总共需要爬的层数为Y-N1+(N2+N3)=Y-
(N1-N2-N3)层。

反之,如果电梯在i+1层停那么乘客总共需要爬的层数为Y+
(N1+N2-N3)层。由此 可见,当N1>N2+N3时,电梯在第
i-1层停更好,乘客走的楼层数减少N1-N2-N3层;当 N1+N2
int n=0;这个表示电梯所在的最高楼层
int nPerson[] = new int[n+1];这个数组表示要去每
一层的乘客数
上面的两个变量应该是给出的,这里只是示意代
码没有初始化。
int nMinFloor = 0,nTargetFloor = 1;分别表示目前
为止的最小结果,最小结果所停的楼层。
int N1 = 0 , N2 = nPerson[1] , N3 = 0;分析中所说的
N1,N2,N3创建和初始化
求出第二层时候的N3值并初始化
for(int k = 2; k <= n;k++){
N3 += nPerson[k];
nMinFloor += nPerson[k] *(k-1);
}
从第二层开始按照上述方法求出最优值


for(int i = 2; i <= n i++){
if( (N1 + N2) < N3){如果i+1层更好,就替换
最小结果,
nTargetFloor = i
nMinFloor += (N1 +N2 - N3);
N1 += N2;
N2 = nPerson[i];
N3 -= nPerson[i];
}else{如果上面的楼层不会更好,就不用再查
看了。
break;
}
}2
问题扩展 < br>往上爬楼梯,总比往下走是要累的,假设往上爬一个楼层,
需要消耗k个单位的能力,而往下走需 要消耗一个单位的能
量,那么如果题目条件改为让所有人消耗的能量最少,这个
问题怎么解决呢 ?
分析
其实这个问题并没有变难太多,只是在前面的思考的前提下
放入一个新的考 虑:上下楼消耗能量。这个需要在计算的时
候上楼就要乘以一个参数K(因为能量是下楼的k倍嘛),其 他


的考虑都还一样。
int n=0,k = 1;这个表示电梯所在的最高楼层和上楼梯需要
消耗的能量
int nPerson[] = new int[n+1];这个数组表示要去每
一层的乘客数
上面的变量应该是给出的,这里只是示意代码没
有初始化。
int nMinFloor = 0,nTargetFloor = 1;分别表示目前
为止的最小结果,最小结果所停的楼层。
int N1 = 0 , N2 = nPerson[1] , N3 = 0;分析中所说的
N1,N2,N3创建和初始化
求出第二层时候的N3值并初始化
for(int m = 2; m <= n;m++){
N3 += nPerson[m];
nMinFloor += nPerson[m] *(m-1);
}
从第二层开始按照上述方法求出最优值
for(int i = 2; i <= n i++){
if( k*(N1 + N2) < N3){如果i+1层更好,就替
换最小结果,
nTargetFloor = i
nMinFloor += (k*(N1 +N2) - N3);


}
N1 += N2;
N2 = nPerson[i];
N3 -= nPerson[i];
}17181920
补充说明
其实目前为止的逻辑过于不切实际,因为实际中在高层电梯< br>中不会出现只停一层的情况,而且如果有类似的政策的话,
比较低的楼层的人会直接选择爬楼去而 不去按电梯(即使是
统计好人数也会在计算总体的消耗上有很大的不同)。

庾澄庆资料-辞职申请书范文


以偶像为话题的作文-幼儿园新学期计划


2012年高考-常州大学教务系统


华夏典当行-培训学习总结


拜新年-加拿大新闻


雨的成语-湘潭大学教务处


德国音乐学院-干部作风整顿心得体会


销售动员大会发言稿-搞笑生日祝福短信