野人傳教士問題 盲目搜尋

2021-04-08 12:38:47 字數 3049 閱讀 3460

從前有一條河,河的左岸有

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 船上...