小飛的電梯排程演算法
1、問題描述:
某大廈一共有6部電梯,在高峰時間,每層都有人上下,電梯在每層都停,實習生小飛常常會被每層都停的電梯弄的很不耐煩,於是他提出了這樣一個辦法:由於樓層不太高,每次電梯往上走時,我們只允許電梯停在其中的某一層。所有乘客都從一樓上電梯,到達某層後,電梯停下來,所有乘客再從這裡爬樓梯到自己的目的層。在一樓的時候,每個乘客選擇自己的目的層,電梯自動計算出相應的樓層。電梯應停在哪一層,能夠保證這次乘坐電梯的所有乘客爬樓梯的層數之和最小?
2、分析:
該問題本質上是一個優化問題,從問題中我們可以看到,影響結果的主要有兩個因素:乘客人數和電梯停的層數。假設樓層總共有N層,電梯停在x層,到第i層的乘客人數為Tot[i],則所爬樓梯的總數是:|x-1|*Tot[1]+|x-2|*
3、解法:
<1>解法一
可以從第一層開始來列舉x,一直到第N層,然後計算出乘客所爬樓梯的總數,並求出最小值以及此時的x的值。這個演算法的時間複雜度為O(n*n)。
執行結果:#include <iostream> using namespace std; void min_floor(int floor_num,int tot_person[]);//參一:樓層總數;參二:去每層的人數 int main() { int tot_person[7] = { 0,1, 2, 2, 0, 3, 2 }; min_floor(6, tot_person); } void min_floor(int floor_num, int tot_person[]) { int i,j, minFloor,total_floor = 0, target_floor = -1; for (i = 1; i <= floor_num;i++) { for (j = 1; j <= i; j++) total_floor += tot_person[j] * (i - j); for (j = i + 1; j <= floor_num;j++) total_floor += tot_person[j] * (j - i); if (target_floor == -1 || minFloor > total_floor) { target_floor = i; minFloor = total_floor; } total_floor = 0; } cout << "目標樓層:" << target_floor << endl << "最少層數:" << minFloor << endl; }
<2>解法二
假設電梯停在第i層樓,那我們可以計算出所有乘客爬的總樓層數Y。如果有N1個乘客目的樓層在i層樓以下,N2個乘客目的樓層在i層樓,N3個乘客在i層樓以上。在這種情況下,如果電梯改停在(i+1)層,那麼目的樓層在i層以上的乘客將少爬一層,即N3個乘客將少爬N3層,目的樓層在i層及i層以下的乘客將多爬一層,及多爬(N1+N2)層,因此所有乘客爬的樓層數為Y-N3+N1+N2 = Y+(N1+N2-N3)。同理可以求的電梯改停在(i-1)層時,乘客所爬的樓層總數為Y-(N1-N2-N3)。由此可見當N1+N2
< N3時乘客少爬的樓層數為N3-N1-N2,電梯在i+1層停更好;如果N2+N3 < N1,乘客少爬的樓層數為N1-N2-N3,電梯停在i-1層更好;其它情況停在i層更好。
根據這個規律我們從第一層開始考察,計算乘客所爬樓梯的總數。然後再根據上面的策略進行調整,直到找到最佳樓層。總的時間複雜度為O(N)。
#include <iostream>
using namespace std;
void min_floor_second(int floor_num, int tot_person[]);//參一:樓層總數;參二:去每層的人數
int main()
{
int tot_person[7] = { 0,1, 2, 2, 0, 3, 2 };
min_floor_second(6,tot_person);
}
void min_floor_second(int floor_num, int tot_person[])
{
int N1 = 0, N2 = tot_person[1], N3 = 0;
int i, target_floor = 1,min_floor = 0;
for (i = 2; i <= floor_num; i++)
{
N3 += tot_person[i];
min_floor += tot_person[i] * (i - 1);
}
for (i = 2; i <= floor_num;i++)
{
if ( (N1 + N2) < N3)
{
target_floor = i;
min_floor += (N1 + N2 - N3);
N3 -= tot_person[i];
N1 += N2;
N2 = tot_person[i];
}
else
break;
}
cout << "目標樓層:" << target_floor << endl << "所爬層數:" << min_floor << endl;
}
執行結果: