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

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

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

思路:

1、暴力方法。依次停留在每一層,求出最小的爬樓梯數,時間複雜度為O(N*N);

2、假設停留在第i層,設此時往下走的為N1,停留在當前的為N2,往上走的步數為N3,那麼如果選擇i+1層,必須滿足條件(N2+N3)-N1>0,根據這個分析結果,可以不斷地調整。

3、這個題目還可以採用中位數的思想,根據1-6層可以看做求一個帶權陣列的加權平均數。

具體程式碼如下:

#include <iostream>

using namespace std;

const int INF = 1<<31 -1;
//暴力演算法
int brute_force(int A[],int N)
{
    int sum = INF;
    int tmp = 0;
    int itarget = 0;
    for(int i =0;i < N;i ++)
    {
        tmp = 0;
        for(int j = i-1;j >= 0;j --)
        {
            tmp += A[j]*(i-j);
        }
        for(int j = i+1;j < N;j ++)
        {
            tmp += A[j]*(j-i);
        }
        if(tmp < sum )
        {
            sum = tmp;
            itarget = i;
        }
    }
    return itarget;
}
/*
*N1為i層以下的人數
*N2為i層人數
*N3為i層以上的人數
*Y(i+1) = Y(i)+N3-N2-N1;
*/
int dynamic(int A[],int N)
{
    int N1 = 0;
    int N2 = 0;
    int N3 = 0;
    int itarget = 0;
    N2 = A[0];
    for(int i = 1;i < N;i ++)
    {
        N3 +=A[i];
    }
    for(int i = 1;i < N;i ++)
    {
        if(N3 > N2 +N1)
        {
            N1 += N2;
            N2 = A[i];
            N3 -= A[i];
            itarget = i;
        }
        else break;
    }
    return itarget;
}
/*
*
*求加權中位數,這裡start是否是最終的解還有待商榷,
*因為有可能是mend是最終解,所以後期還需要略微比較一下
*/

int mymid(int A[],int N)
{
    int mstart = 0;
    int mend = N-1;
    while (mend -mstart > 1)
    {
        while(A[mstart] == 0) mstart ++;
        A[mstart]--;
        while(A[mend] == 0) mend --;
        A[mend] --;
    }
    return mstart;
}

int main ()
{
    int A[]= {2,3,5,5,6,7,8,8,9};
    cout << mymid(A,9);
}

reference: