電梯系列,自然要從最簡單的單電梯場景開始。
1,電梯狀態
電梯狀態可以分爲空閒、開門、上下移動三個狀態,爲了便於理解,我們可以忽略開門狀態。
也就是說,電梯分爲空閒狀態和移動狀態。
2,樓層
一般有2種,一種是1~n層,沒有地下,一種是1~n層和-1~-m層,有地下m層。
在不影響核心研究內容的前提下,默認只考慮第一種,1~n層,沒有地下。
3,電梯輸入
電梯外輸入一般有2種,一種是上下按鈕,一種是樓層數值按鈕。
電梯內輸入都是直接按樓層。
4,比較容易想到的控制算法
先來先服務算法(FCFS)、最短尋找時間優先算法(SSTF)、掃描算法(SCAN)
這三個都是和操作系統的調度算法相通的,我就不解釋含義了。
先來先服務算法會造成效率很低,最短尋找時間優先算法會造成飢餓等待,都是不可取的。
所以電梯都是基於掃描算法進行優化的。
5,簡單掃描算法
如何模擬呢?
可以抽象爲2個函數,一個是輸入,包括外部輸入和內部輸入,一個是輸出,顯示電梯實時狀態。
利用多線程,可以實時控制輸入和輸出函數同時運行。
本來是構思2個輸入函數的,因爲多線程不熟,避免輸入流的麻煩,就合到一起了,用控制字來描述。
每次輸入lev和fla,如果fla爲0,表示內部輸入要去lev樓,如果fla爲1,2,3,表示lev樓有乘客按了上下行。
注意:
(1)代碼健壯性很弱,需要嚴格按照預定方式輸入。
(2)外部輸入的方式是直接覆蓋式的,測試的時候需要人工避免一些奇怪的值。
(3)需要人工控制輸入時間,並不是一開始就全部把數據粘貼進去
#include <thread>
#include<time.h>
#define LEVEL 6
int flag[LEVEL + 1]; //1到Level層的外部輸入,取值爲0,1,2,3,其中0表示無乘客,1表示有乘客上行,2表示有乘客下行,3表示既有上行又有下行
int dest[LEVEL + 1]; //目的樓層的記錄,取值爲0,1,其中0表示不是目的地,1表示是目的地
void input()
{
int lev, fla;
while (cin >> lev >> fla) if (lev > 0 && lev <= LEVEL)
{
if(fla>0 && fla<=3)flag[lev] = fla; //外部輸入
else dest[lev] = 1;//內部輸入
}
}
void upPull(int loc)//上行接客
{
flag[loc]--;
cout << "上行接客"<<loc<<endl;
}
void downPull(int loc)//下行接客
{
flag[loc] -= 2;
cout << "下行接客" << loc << endl;
}
void push(int loc)//送客
{
dest[loc] = 0;
cout << "送客" << loc << endl;
}
void run()
{
int loc = 1;
while (1)
{
for (loc = 1; loc <= LEVEL; loc++)
{
cout << " 當前樓層" << loc << endl;
if (flag[loc] == 1 || flag[loc] == 3)upPull(loc);
if (dest[loc])push(loc);
Sleep(1000);
}
for (loc = LEVEL; loc>0; loc--)
{
cout << " 當前樓層" << loc << endl;
if (flag[loc] == 2 || flag[loc] == 3)downPull(loc);
if (dest[loc])push(loc);
Sleep(1000);
}
}
}
int main()
{
thread t1(input);
thread t2(run);
t1.join();
t2.join();
return 0;
}
模擬示例:
示例1
示例2