算法題009 電梯調度算法


電梯調度算法

 

題目描述

  大廈中有電梯,在高峰時間,每層都有人上下,電梯在每層都停。

  想的解決辦法如下:

  所有的乘客都從一樓上電梯,每個乘客選擇自己的目的層,之后電梯自動計算出一個樓層。

  電梯往上走時,只在這個樓層停下來,所有的乘客再從這里爬樓梯到自己的目的樓層。

  現在就想問,電梯停在哪一層樓,能夠保證這次乘坐電梯的所有乘客爬樓梯的層數之和最少。

 

  該問題本質上是一個優化問題

  首先為這個問題找到一個合適的抽象模型。

  有兩個因素會影響結果:乘客的數目和乘客的目的樓層。

  假設樓層總共有N層,電梯停在x層,要去第i層的乘客數目總數為Tot[i],這樣,所爬樓梯的總數就是:

  

                                                   

  因此,我們就是需要找到一個整數x,使得上式的值最小。

 

解法一

  最為直接的一個解法就是從第一層開始,枚舉x一直到第N層,計算出電梯在第x層樓停的話,所有乘客總共需要爬多少樓。

  這個算法需要兩重循環來完成。

  代碼如下:

解法一
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    int N = 0;
    int nPerson[100];
    int nFloor, nMinFloor, nTargetFloor;
    nTargetFloor = -1;

    while( cin >> N) //輸入總的樓層
    {
        //進行狀態清零
        nTargetFloor = -1;
        nMinFloor = 0;

        //輸入到每一層的人的個數
        for(int i = 0; i < N; ++i)
        {
            cin >> nPerson[i];
        }

        //開始計算最佳樓層
        for(int i = 0; i < N; ++i)
        {
            //對於每一個樓層,先假設是停在這個樓層

            //用一個變量記錄要步行的樓層總數
            nFloor = 0;

            //假設停在第i層,統計所有人需要步行的樓層總數
            for(int j = 0; j < N; ++j)
            {
                if(j < i)
                {
                    nFloor += nPerson[j] * (i - j);
                }
                else if(j > i)
                {
                    nFloor += nPerson[j] + (j - i);
                }

            }

            //第一次記錄,或者當前結果小於之前最小時,記錄結果

            if(-1 == nTargetFloor || nMinFloor > nFloor)
            {
                nMinFloor = nFloor;
                nTargetFloor = i;
            }
        }

        //輸出計算結果
        cout << "The best floor is:  " << nTargetFloor + 1 << 

endl;

    }

    return 0;
}

 

  這個基本解法的時間復雜度為O(N2)。

 

解法二

  假設電梯停在i層,我們可以計算出所有乘客總共需要爬樓梯的層數Y。

  假設有N1個乘客在i層樓以下,N2個乘客在第i層樓,還有N3個乘客在第i層樓以上

  這個時候,如果電梯改停在i-1層,所有目的地在第i層及以上的乘客都需要多爬一層,即N2+N3層,而所有目的地在i-1層及以下的乘客可以少爬一層,總共可以少爬N1層。

  因此,乘客總共需要爬的層數為Y-N1+N2+N3 = Y-(N1-N2-N3)層

  反之,如果電梯在i+1層停,則總共需要爬的層數為Y+(N1+N2-N3)層。

  由此可見:

  當N1 > N2 + N3時,i-1層比i層好;

  當N1 + N2 < N3時,i+1層比i層好。

  根據這個規律,我們從第一層開始考察,計算各位乘客需要爬樓梯的層數。然后再根據上面的策略進行調整,直到找到最佳樓層。

解法二
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    int N = 0;
    int nPerson[100];
    int nMinFloor, nTargetFloor;
    int N1, N2, N3;


    while( cin >> N) //輸入總的樓層
    {
        //輸入到每一層的人的個數
        for(int i = 0; i < N; ++i)
        {
            cin >> nPerson[i];
        }

        //進行狀態清零
        nTargetFloor = 0;
        nMinFloor = 0;

        N1 = 0; 
        N2 = nPerson[0];
        N3 = 0;

        for (int i = 1; i < N; ++i)
        {
            N3 += nPerson[i];
            nMinFloor += nPerson[i] * (i - 1);
        }

        for(int i = 1; i < N; ++i)
        {
            if(N1 + N2 < N3)
            {
                nTargetFloor = i;
                nMinFloor +=(N1 + N2 - N3);

                N1 += N2;
                N2 = nPerson[i];
                N3 -= N2;
            }
            else
            {
                //否則第i層的結果已經最小,故不需要計算第i+1層 
                break;
            }
        }



        //輸出計算結果
        cout << "The best floor is:  " << nTargetFloor + 1 << endl;

    }

    return 0;
}

 

  總的時間復雜度將降為O(N)。

 

參考資料

  《編程之美》1.8節

  相關博客:http://www.cppblog.com/jake1036/archive/2011/06/29/149720.html?opt=admin

 

  PS:

  每天更新有點扛不住了,還是不要強求每天了。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM