zoukankan      html  css  js  c++  java
  • 编程之美 1.8小飞的电梯调度算法

    题目:

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

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

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

    用数组nPerson[i]存放在第i层下楼的人数,在不同的i层停靠,求所有人需要走的楼层总和,找出总和最小的楼层Target,输出。用两重循环完成计算。

     1 /*
     2 * 1.8.1
     3 *
     4 *  Created on: Jan 9, 2016
     5 *      Author: SeekHit
     6 */
     7 #include "iostream"
     8 #define N 100
     9 
    10 using namespace std;
    11 
    12 int func(int n, int nPerson[]){
    13 
    14     int nFloor, nMinFloor=0, TargetFloor=0;
    15 
    16     for (int i = 1; i <= n; i++){
    17         nFloor = 0;
    18         for (int j = 1; j<i; j++)
    19             nFloor += (i - j)*nPerson[j];
    20         for (int j = i + 1; j <= n; j++)
    21             nFloor += (j - i)*nPerson[j];
    22 
    23         if (TargetFloor==0||nMinFloor>nFloor){    //如果没有TargetFloor==0,nMinFloor>nFloor始终无法满足,不执行if里面的内容 
    24             nMinFloor = nFloor;
    25             TargetFloor = i;
    26 
    27         }
    28     }
    29     return TargetFloor;
    30 }
    31 
    32 int main(){
    33     int n, Target;
    34     int nPerson[N];
    35     cout<<"输入楼层总数n:"<<endl;
    36     cin>>n;
    37     cout<<"输入每层楼下的人数"<<endl;
    38     for (int i = 1; i <= n; i++){
    39         cout<<""<<i<<"层下的人数:"<<endl;
    40         cin>>nPerson[i]; 
    41     }
    42 
    43     Target = func(n, nPerson);
    44     cout<<"电梯停靠最优层数为:"<<Target<<endl;
    45 }

    方法二:时间复杂度为O(N)的动态规划的算法

    降低时间复杂度,求解。假设停在i层,可以计算出所有乘客需要爬的楼层总数Y。设N1个人在i层以下下楼,N2个人在i层下楼,N3个人在i层以上下楼。

    如果现在电梯改在i-1层停靠,现在所有i层和i层以上的都要多走一楼,相当于,总共多爬了N2+N3层,而i层以下的所有人少爬了一楼,就是少了N1层。总数变成了N2+N3-N1层,如果N2+N3-N1<Y,说明降一层停靠更优。

    反之,如果i+1层停靠,所有乘客爬的楼层数变成了N1+N2-N3,如果N1+N2-N3<Y说明升一层停靠更优。

    书上给的程序就是用升楼的方式来判断的,也可以用降楼来动态规划最优楼层数。

     1 /*
     2 * 1.8.2动态规划 
     3 *
     4 *  Created on: Jan 9, 2016
     5 *      Author: SeekHit
     6 */
     7 #include "iostream"
     8 #define N 100
     9 
    10 using namespace std;
    11 
    12 int func(int n, int nPerson[]){
    13 
    14     int nMinFloor=0, TargetFloor=1;
    15     int N1=0,N2=nPerson[1],N3=0;
    16 
    17 //计算N3,就停靠在1楼时,需要走的总楼层数 
    18     for (int i = 2; i <= n; i++){
    19         N3+=nPerson[i];
    20         nMinFloor+=nPerson[i]*(i-1);
    21     }
    22     
    23     for(int i=2;i<=n;i++){
    24         if(N1+N2<N3){
    25             TargetFloor=i;
    26             nMinFloor+=(N1+N2-N3);
    27             N1+=N2;
    28             N2+=nPerson[i];
    29             N3-=nPerson[i]; 
    30         }
    31         else
    32             break;
    33     }
    34     return TargetFloor;
    35 }
    36 
    37 int main(){
    38     int n, Target;
    39     int nPerson[N];
    40     cout<<"输入楼层总数n:"<<endl;
    41     cin>>n;
    42     cout<<"输入每层楼下的人数"<<endl;
    43     for (int i = 1; i <= n; i++){
    44         cout<<""<<i<<"层下的人数:"<<endl;
    45         cin>>nPerson[i]; 
    46     }
    47 
    48     Target = func(n, nPerson);
    49     cout<<"电梯停靠最优层数为:"<<Target<<endl;
    50 }

    运行结果:

    扩展问题:

    往上爬比往下走要累,往上爬一层消耗k个单位的能量,往下走只消耗1个单位的能量,求让所有人消耗的能量最少。

    解法:

    只需将计算N1+N2-N3变成N1+N2-N3*K即可。其余的都一样。

  • 相关阅读:
    particcles.js in 安卓WebView
    PDF.js 主页样式以及获取流
    Oracle授权A中的表给B
    安卓Response 获取body的正确方式
    android.util.Base64 和 org.apache.commons.codec.binary.Base64
    DAY62-前端入门-javascript(九)jQurey高级
    DAY61-前端入门-javascript(八)jQurey
    DAY60-前端入门-javascript(七)JS动画 | JS盒模型 | DOM | BOM
    DAY59-前端入门-javascript(六)JS事件
    DAY58-前端入门-javascript(五)JS常用类
  • 原文地址:https://www.cnblogs.com/SeekHit/p/5116557.html
Copyright © 2011-2022 走看看