1. 程式人生 > >《程式設計之美》小飛的電梯排程演算法

《程式設計之美》小飛的電梯排程演算法

亞洲微軟研究院所在的希格瑪大廈一共有6部電梯。在高峰時間,每層都有人上下,電梯每層都停。實習生小飛常常會被每層都停的電梯弄的很不耐煩,於是他提出了這樣一個辦法:
由於樓層並不算太高,那麼在繁忙的上下班時間,每次電梯從一層往上走時,我們只允許電梯停在其中的某一層。所有乘客從一樓上電梯,到達某層後,電梯停下來,所有乘客再從這裡爬樓梯到自己的目的層。在一樓的時候,每個乘客選擇自己的目的層,電梯則計算出應停的樓層。
問:電梯停在哪一層樓,能夠保證這次乘坐電梯的所有乘客爬樓梯的層數之和最少?
解法一:暴力列舉法。從第1層列舉到第N層,求出電梯在x層停的話,所有乘客需要怕多少層樓。求出最少的那層即可。程式碼略。
解法二:動態規劃。假設電梯停在第x層,已知目的樓層在x層的有N2人,在x層以下的有N1人,在x層以上的有N3人。此時總花費為sum。則往上走一層的話,總花費變為sum + N2 + N1 - N3。那麼初始狀態電梯停在第一層,向上進行狀態的變遷,開始時N2 + N1 - N3 < 0。sum越來越小,直到某一層N2 + N1 >= N3,就沒有必要在往上走了。這時已求出最合適的樓層了。
解法三:我的方法。哈哈。其實沒有那麼複雜。假設只有兩個人,一個去9層,一個去2層,那麼不管電梯停在2至9層中間的任何樓層,兩個人的總花費都是7.就比如在數軸上點2和點9中間的任何點距離2和9的距離之後都是7。那麼停在哪都無所謂了。接著我們擴充套件開來,假設有N個人,他們的目標樓層分別是2,3,3,4,5,5,5,7,7,8,9。按我們的想法,對於兩端的(2,9)電梯只要停在他們之間都一樣。同理對於(3,8)電梯只要停在他們中間都一樣……。最終電梯只要停在中間那個數即可。也就是中位數。原來弄半天只需求出中位數即可啊。如果N是偶數個的話,停在中間那兩個數任何一個都可以的。歡迎大家對我的解法拍磚。程式碼就不用了吧。
擴充套件問題的解法:
如果往上爬樓梯比較累,往下走較容易,假設往上走一層耗費k單位的能量,往下走一層只耗費1單位的能量。此時就不適合用我的解法三了,解法二更加適合。程式碼如下:

int controlElevator(int nPerson[], int nfloor, int upWeight){
    int targetFloor = 1;
    int minFloor = 0;
    int N1 = 0;
    int N2 = nPerson[1];
    int N3 = 0;
    int i = 0;
    for(i = 2; i <= nfloor; i++){ //i表示大眾意義上的第i層
        N3 += nPerson[i];
        minFloor += (nPerson[i] * (i - 1) * upWeight);
    }
    for
(i = 2; i <= nfloor; i++){ if(N1 + N2 < N3 * upWeight){ minFloor += (N1 + N2 - N3 * upWeight); N3 -= nPerson[i]; N1 += N2; N2 = nPerson[i]; targetFloor = i; } else break; } return minFloor; // return targetFloor;
}

下面附上我的解法三的程式碼:

int main(){ 
    int nPerson[9]={0,1,1,0,2,1,1,2,1};
    int left=0, right=8;
    while(right-left > 1){
        while(nPerson[left] == 0)
            ++left;
        nPerson[left]--;
        while(nPerson[right] == 0){
            if(right < left)
                break;
            --right;
        }           
        nPerson[right]--;
    }
    cout<<left+1<<endl; 
    return 0;
}

相關推薦

程式設計》讀書筆記[電梯排程演算法]

   在高峰時間,實習生小飛常常會被電梯每層樓都停弄得很不耐煩,於是他想出了這樣一個辦法:由於樓層並不高,那麼在繁忙的時間,每次電梯從一層往上走時,我們只允許電梯停在其中的某一層。所有乘客都從一樓上電梯,到達某層樓後,

程式設計電梯排程演算法(多種解法)---Java語言

1.題目情景         我們假設都是從一樓上電梯的,而至於訊電梯停在其中的某一層。即所有的乘客都從一樓上電梯,到達某層之後,電梯停下來,所有乘客再從這裡爬樓梯到自己的目的層。在一樓的時候,每個乘客選擇自己的目的層,電梯則自動計算出應停的樓層,並且能夠保證該層停使得所有

程式設計電梯排程演算法

亞洲微軟研究院所在的希格瑪大廈一共有6部電梯。在高峰時間,每層都有人上下,電梯每層都停。實習生小飛常常會被每層都停的電梯弄的很不耐煩,於是他提出了這樣一個辦法: 由於樓層並不算太高,那麼在繁忙的上下班時間,每次電梯從一層往上走時,我們只允許電梯停在其中的某一層

程式設計 1.8電梯排程演算法的第三種解

原題目如下: 亞洲微軟研究院所在的希格瑪大廈一共有6部電梯。在高峰時間,每層都有人上下,電梯每層都停。實習生小飛常常會被每層都停的電梯弄的很不耐煩,於是他提出了這樣一個辦法: 由於樓層並不算太高,那麼在繁忙的上下班時間,每次電梯從一層往上走時,我們只允許電梯停在其中的某

電梯排程演算法@程式設計

題目:(程式設計之美 1.8)一棟樓有6層,現在設計一種電梯排程演算法:電梯在一樓讓大家上電梯,然後根據大家選擇要到的樓層算出某一樓層i,電梯在i層停下讓所有人下電梯,然後大家爬樓梯達到自己的樓層。請問電梯停在哪一層,可以使得這一次的所有乘客爬樓層之和最短? 思路: 1、暴

程式設計1.8電梯排程演算法擴充套件問題

設有N2個乘客在第i層下,N1個乘客的目的地樓層在第i層以下,N3個乘客的樓層在第i層以上 假設電梯從停在i層改停在為i+1層,停在第i層時消耗的總能量為E 則改為i+1層停之後原先i層以上的乘客即N3個乘客少往上爬一層,原先第i層的N2個乘客需多往下爬一層,原先第i層以下

程式設計--遊戲樂--1.8電梯排程問題

o(n)解法 利用Y來儲存以當前i層為基準,所有員工需要走的樓層 N1 i層以下所有人數 N2 第i層的人數 N3 i層以上的人數 可以得出: Y = Y(i-1需要走的樓層)+N1-N2

程式設計---電梯排程演算法

在看linux 0.11版本的塊裝置驅動部分,裡面提到了電梯演算法,總結下幾種尋道的方式。         第一種:最為原始的先到先服務(first come first served)的演算法。假設此時我們正在第11道讀取資料,然後陸陸續續有其他程序來要求我們提供磁碟內容

電梯排程演算法

1、問題描述: 某大廈一共有6部電梯,在高峰時間,每層都有人上下,電梯在每層都停,實習生小飛常常會被每層都停的電梯弄的很不耐煩,於是他提出了這樣一個辦法:由於樓層不太高,每次電梯往上走時,我們只允許電

程式設計電梯排程問題

電梯排程問題:亞洲微軟研究院所在的希格瑪大廈一共有6部電梯。在高峰時間,每層都有人上下,電梯每層都停。實習生小飛常常會被每層都停的電梯弄的很不耐煩,於是他提出了這樣一個辦法: 由於樓層並不算太高,那麼在繁忙的上下班時間,每次電梯從一層往上走時,我們只允許電梯停在其中的

最長遞增子序列程式設計232演算法

#include <stdio.h> #include <stdlib.h> int a[100];//儲存原始序列 int LIS[100];//儲存以a[i]為最大元素的最長遞增子序列的長度 int MaxV[100];//儲存長度為i的遞增子序

程式設計——一摞烙餅的排序(暴搜+剪枝)

題目 分析 深度優先搜尋遍歷每一種情況,去翻轉次數最小的,當然,還要加一些剪枝,畢竟O(nn)的時間複雜度。 程式碼 C風格 1 /**** 字首排序 ****/ 2 #include<stdio.h> 3 #include<cstring> 4 #incl

電梯排程演算法認識

傳統電梯排程演算法 1.1先來先服務演算法(FCFS) 先來先服務(FCFS-First Come First Serve)演算法,是一種隨即服務演算法,它不僅僅沒有對尋找樓層進行優化,也沒有實時性的特徵,它是一種最簡單的電梯排程演算法。 它根據乘客請求乘坐電梯的先後次序進行排程。

程式設計10:計算字串的相似度

我們並不在乎兩個字串變得相等之後的字串是怎樣的,所以 1.一步操作之後,再將A[2,…,lenA]和B[1,…,lenB]變成相同的字串。 2.一步操作之後,再將A[1,…,lenA]和B[2,…,lenB]變成相同的字串。 3.一步操作之後,再將A[2,…,lenA]和B[2,…,lenB]變成相

程式設計9:陣列迴圈位移

1: RightShift(int *arr, int N, int K) { K %= N; while (K--) { int t = arr[N - 1]; for (int i = N - 1; i > 0; i--)

程式設計8:求陣列的子陣列之和的最大值

1: int MaxSum(int *A, int n) { int maximum = -INF; int sum; for (int i = 0; i < n; i++) { sum = 0; for (int j = i;

程式設計7:最大公約數

1:輾轉相除法 f(x,y) = f(y, x%y); int gcd(int x, int y) { return (!y) ? x : gcd(y, x % y); } 2:對於大整數,取模運算非常昂貴。 f(x, y) = f(x-y, y); BigInt gcd(BigI

程式設計3:求二進位制數中1的個數

1: int Count(BYTE v) { int num = 0; while (v) { if (v % 2 == 1) { num++; } v = v / 2; }

程式設計2:程式只用一個位元組變數,列印將帥位置

原創:https://blog.csdn.net/ndzjx/article/details/84404320 #include <stdio.h> #include <windows.h> #include <time.h> #include <

程式設計1:CPU列印直線,曲線

原創:https://blog.csdn.net/ndzjx/article/details/84404268 1:本質:每次迴圈的CPU比例問題。 CPU排程時間片,大約為20ms 2.2GHz是CPU時鐘週期,= 22億次 = 2.2*10^9 每個時鐘週期平均執行2條彙編指令