從前有一條河,河的左岸有
m個傳教士
(missionary)和m
個野人(cannibal)
,和一艘最多可乘
n人的小船。約定左岸,右岸和船上或者沒有傳教士,或者野人數量少於傳教士,否則野人會把傳教士吃掉。
程式設計,接收m和
n,搜尋一條可讓所有的野人和傳教士安全渡到右岸的方案。
我們先假設左岸有
3個傳教士和
3個野人,小船最多可乘
2人。把當前左岸的狀態抽象為:
(3,3,1)
前兩個
"3"代表左岸有
3個傳教士和
3個野人,
1代表船在左岸。把每一次可行的渡船方案作為算符。比如,在初始狀態,讓
1個傳教士和
1個野人上船並渡到右岸,這一算符可表示為:
(1,1)
算符的兩位數分別代表要移動的傳教士,野人的數量;把人移到沒有船的岸邊並且改變狀態向量中船的值。
對於固定大小的小船,算符的數量是一定的:
class
move ;
class
movegroup
else
if (m==0 && c!=0)
else
if (m+c<=max_on_boat && m+c!=0 && m>=c)
nummove = i;
} };
建立乙個
movegroup
物件movegroup mg(2);
即可得到當小船最多可乘
2人時的算符集。
這個程式所要做的,就是通過這個已知的算符集,將初始狀態
(3,3,1)
轉變為最終狀態
(0,0,0)
。我們應將狀態作為搜尋的元素。
構建類時應注意,並不是每個算符對於任意的狀態都是可以應用的,這需要對應用算符後的安全性進行檢查,以判斷這一算符對當前狀態是否可用;同時,類中也要包含乙個判斷當前狀態是否是最終節點
(0,0,0)
的方法;當然
」==」
,」=」
這兩個運算子以及
null
值,這是呼叫
dso.h
時所不可或缺的。(詳見原始檔)
class
elemtype : move
elemtype() {}
bool
operator
==(elemtype e)
void
operator
=(elemtype e)
elemtype friend
operator
>>(elemtype source, move &mv) else
return
result;
}
bool
issafe(move &mv, int
max_people)
}
bool
issuccess()
//issuccess()
判斷當前狀態是否為最終節點
int
getm()
int getc()
int getb()
void
print()
};
const
elemtype null(0); //(0,0,1)
這是不會出現的
void
print(elemtype &e) //
列印函式
至此,我們已經完成了對問題的描述。
搜尋過程採用較簡單的「寬度優先盲目搜尋」,演算法框圖如下:
#include
"dso.h"
typedef
elemtype status;
當得到了乙個最終節點
(0,0,0)
時,如果我們前邊的操作沒有儲存路徑的話,那麼我們就只知道這個問題有解,而不知道解的具體路徑。還記得在定義
elemtype
時那個旗子指標嗎,用它保留它的父節點的位址,問題就解決了。
open
,closed
表均通過佇列實現。由於對擴充套件節點要儲存指標,所以
closed
表需要乙個獲得尾指標的方法。
class
queuex : public
queue
return
&temp->node;
} };
搜尋得到的答案也儲存在乙個佇列裡,但我們知道:當得到乙個最終節點時,根據它的指向父節點的指標向上搜尋得到的是乙個反的解序列,這裡使用乙個臨時的棧,可以將解的順序調換過來。
class
answer : public
queue
if(s2.issuccess())
this
->enqueue(s0);
while
(!s2.issuccess())
return;
}
} }
}
void
show()
};
就要成功了,通過下面這個宣告就可以得到
max_people
個傳教士,
max_people
個野人,每艘船上最多乘坐
max_on_boat
人的解:
answer answer(max_people, max_on_boat);
通過下面的呼叫可以列出整個解的過程:
answer.show();
源程式 >>>
(在控制台輸入max_people和max_on_boat,然後輸出mco.log演示移動過程)
以前編過乙個c語言版的,不過似乎有記憶體洩漏的八哥,這個版本應該是沒問題了。
完成於2023年6月18日
傳教士野人過河問題
這個問題是人工智慧中經典的搜尋問題,下面用深度優先搜尋演算法來解這個題,示例 如下 include include include using namespace std typedef struct mcnode listfringe 相當於佇列 vectorclosed closed表 判斷是否...
演算法 傳教士和野人問題
有n個傳教士和n個野人來到河邊準備渡河,河岸有一條船,每次至多可供k人乘渡。問傳教士為了安全起見,應如何規劃擺渡方案,使得任何時刻,在河的兩岸以及船上的野人數目總是不超過傳教士的數目。即求解傳教士和野人從左岸全部擺渡到右岸的過程中,任何時刻滿足m 傳教士數 c 野人數 和m c k 的擺渡方案。te...
野人與傳教士過河問題
題目 設有三個 傳教士和3個野人來到河邊,打算乘乙隻船從右岸渡到左岸去。該船的負載能力為兩個人。在任何時候,如果野人人數超過傳教士人數那麼野人就會把傳教士吃掉。他們怎樣才能用這條船安全地把所有人都渡過河去?河岸 a 對岸 b 船上 2c 2y 1c 1y回去 傳教士划船回去 河岸 a 對岸 b 船上...