當前位置:名人名言大全網 - 心情說說 - 高分跪求渡河程序算法!

高分跪求渡河程序算法!

Paddy102列

CSDNBlog |我的主頁|聯系作者|聚合|登錄5篇文章::0個收藏夾::0個評論::0個引用通告。

文章

C++/Visual C++(RSS)

算法設計(RSS)

遊戲開發(RSS)

收集

相冊

保存在檔案中

2004年6月(4)

2004年4月(1)

野蠻過河問題的算法分析

野蠻過河問題的算法分析

野人過河問題屬於人工智能中的壹個經典問題。問題是這樣描述的:有三個牧師(有的翻譯成傳教士)和三個野人過河,只有壹條船可以坐兩個人。在河的兩邊或者船上,如果野人的數量大於祭司的數量,那麽祭司們就有危險了。妳能找到安全過河的方法嗎?

壹、算法分析

我們來看看問題的初始狀態和目標狀態,假設sum分為A銀行和B銀行:

初始狀態:嘉安,3野人,3牧師;

b岸,0野人,0牧師;

船停在A岸,船上0人;

目標狀態:阿安,0野人,0牧師;

b岸,3個野人,3個牧師;

船停在B岸,船上0人。

整個問題抽象為如何從初始狀態通過壹系列中間狀態到達目標狀態。問題狀態的改變是劃船過河造成的,所以合理的渡河操作就成了算子。根據題目要求,可以得到以下五種運算符(根據擺渡方向,也可以理解為10運算符):

杜1野人,杜1牧師,杜1野人1牧師,杜2野人,杜2牧師。

運營商已知後,剩下的核心問題就是搜索方法。本文采用深度優先搜索,通過FindNext(…)函數找出下壹次渡河操作的最佳操作。如果沒有找到,就會返回到它的父節點,看看是否還有其他的兄弟節點可以展開,然後用Process(…)函數遞歸調用FindNext(…),逐層向後展開。

搜索中使用的壹些規則如下:

1.輪渡優先規則:A岸壹次運送的人越多越好(即A岸運送的人越多),野人優先運送;

壹次二岸運送的人越少越好(即二岸運送的人越少越好),牧師優先運送;

2.最後壹個擺渡操作不能重復(與鏈表中的前壹個操作相比),以避免進入無限循環;

3.在任何時候,河兩岸的野人和牧師的數量分別大於等於0和小於等於3;

4.因為只找到最優解,所以當壹個運算符(目前優先級最高)滿足運算條件時,不搜索其兄弟節點,而是直接加載到鏈表中。

5.如果在展開節點A時沒有找到合適的子節點,則從鏈表中返回節點A的父節點B,從上次選擇的算子中找到優先級最高的算子繼續展開B..

二、基本數據結構

仔細閱讀問題,可以發現壹些必須要把握的基本東西,比如每壹個時刻河兩岸的野人牧師數量,船的狀態,整個問題的狀態。因此,我們定義了以下數據結構:

typedef struct _ riverside//Shore state類型

{

int wildMan//野人數量

教士之間;//牧師人數

}濱江;

Typedef struct _boat //船的狀態類型。

{

int wildMan//野人數量

教士之間;//牧師人數

}船;

Typedef struct _question //整個問題狀態

{

濱江RIVERSIDE 1;//嘉安

濱江河畔2;//B銀行

int端;//船的位置是A岸-1,b岸1。

舟舟;//船的狀態

_ question * pPrev//指向上壹個輪渡操作

_ question * pNext//指向下壹個輪渡操作。

}問題;

使用QUESTION聲明壹個基本鏈表。

三、程序流程和具體設計

本文只求最優解。據我所知,這個問題有三種解決方法。如果妳真的想搞清楚這三個解決方案,_,妳得加強鏈表的操作,比如自己寫壹個動態鏈表類,順便完成壹些初始化工作,估計會更順手。

下面給出了壹些關鍵步驟:

//主函數

int main()

{

//初始化

QUESTION* pHead =新問題;

pHead-& gt;river side 1 . wild man = 3;

pHead-& gt;river side 1 . churchman = 3;

pHead-& gt;river side 2 . wild man = 0;

pHead-& gt;river side 2 . church man = 0;

pHead-& gt;side =-1;//船在a岸。

pHead-& gt;pPrev = NULL

pHead-& gt;pNext = NULL

pHead-& gt;boat . wild man = 0;

pHead-& gt;boat . churchman = 0;

if(進程(pHead))

{

//...遍歷鏈表並輸出結果。

}

cout & lt& lt“渡河成功。”;

}

其他

cout & lt& lt“我們怎麽過河?郁悶!”& lt& ltendl

//回收內存空間

while (pHead)

{

QUESTION * pTemp = pHead-& gt;pNext

刪除pHead

pHead = pTemp

}

pHead = NULL

返回0;

}

//擺渡進程,遞歸調用函數FindNext(...)

布爾過程(問題*問題)

{

if (FindNext(pQuest))

{

QUESTION* pNew =新問題;

pNew-& gt;river side 1 . wild man = p quest-& gt;river side 1 . wild man+pQuest-& gt;boat . wild man *(p quest-& gt;側);

pNew-& gt;river side 1 . churchman = p quest-& gt;river side 1 . churchman+pQuest-& gt;boat . churchman *(p quest-& gt;側);

pNew-& gt;河邊2 . wild man = 3-pNew-& gt;river side 1 . wild man;

pNew-& gt;河邊2 . churchman = 3-pNew-& gt;river side 1 . churchman;

pNew-& gt;side =(-1)* p quest-& gt;側面;

pNew-& gt;pPrev = pQuest

pNew-& gt;pNext = NULL

pNew-& gt;boat . wild man = 0;

pNew-& gt;boat . churchman = 0;

pQuest-& gt;pNext = pNew

if(pNew-& gt;河邊2 .懷爾德曼= = 3 & amp& amppNew-& gt;河邊2 .教士==3)

返回TRUE//完成

退貨流程(pNew);

}

其他

{

quest * PP rev = p quest-& gt;pPrev

if (pPrev == NULL)

返回FALSE//無解

刪除pQuest

pPrev-& gt;pNext = NULL

退貨流程(PP rev);//返回其父節點並重試。

}

返回TRUE

}

//判斷是否有下壹個交叉操作,即根據比較算子找出能靠近目標節點的操作。

//運算符***5: 1野/1牧/1野1牧/2野/2牧。

BOOL FindNext(問題*問題)

{

//基本規則

//渡船優先:壹是岸上運送人多,野人優先;人少的b岸運優先,牧師優先。

靜態船boatState[5];// 5個運算符

if(pQuest-& gt;side == -1)

{

船州[0]。wild man = 2;

船州[0]。churchMan = 0;

boatState[1]。wild man = 1;

boatState[1]。churchMan = 1;

船州[2]。wild man = 0;

船州[2]。churchMan = 2;

船州[3]。wild man = 1;

船州[3]。churchMan = 0;

船州[4]。wild man = 0;

船州[4]。churchMan = 1;

}

其他

{

船州[0]。wild man = 0;

船州[0]。churchMan = 1;

boatState[1]。wild man = 1;

boatState[1]。churchMan = 0;

船州[2]。wild man = 0;

船州[2]。churchMan = 2;

船州[3]。wild man = 1;

船州[3]。churchMan = 1;

船州[4]。wild man = 2;

船州[4]。churchMan = 0;

}

int I;//用於控制運算符

if(pQuest-& gt;boat.wildMan = = 0 & amp& amppQuest-& gt;船。丘吉爾= = 0)//初始狀態,第壹次過河的時候。

I = 0;//運算符1

其他

{

for(I = 0;我& lt5;I++) //擴展同壹個節點時,已經使用的運算符不再使用,優先使用。

if(pQuest-& gt;boat.wildMan == boatState[i]。懷爾德曼& amp& amppQuest-& gt;boat.churchMan == boatState[i]。教士)

打破;

i++;

}

如果(我& lt5)

{

int j;

for(j = I;j & lt5;j++)

{

int nwildman 1 = p quest-& gt;river side 1 . wild man+boat state[j]。wild man * pQuest-& gt;側面;

int nchurchman 1 = p quest->;河邊1 .教會人士+船州[j]。churchMan * pQuest-& gt;側面;

int nwildman 2 = 3-nwildman 1;

int nchurchman 2 = 3-nchurchman 1;

//判斷這個操作的安全性,即牧師人數> =野人或牧師人數為0。

if((nwildman 1 & lt;= nchurchman 1 | | nchurchman 1 = = 0)& amp;& amp

(nWildMan2 & lt= nchurchman 2 | | nchurchman 2 = = 0)& amp;& amp

nwildman 1 & gt;= 0 & amp& ampnchurchman 1 & gt;= 0 & amp& ampnWildMan2 & gt= 0 & amp& ampnChurchMan2 >= 0)

{

//這個操作是否重復上壹個操作,註意方向不同。

if(pQuest-& gt;pPrev!=空)

{

if(pQuest-& gt;pPrev-& gt;boat.wildMan == boatState[j]。懷爾德曼& amp& amp

pQuest-& gt;pPrev-& gt;boat.churchMan == boatState[j]。教士)

繼續;

}

打破;//此操作可行,並推導出循環,只找到當前最優節點。

}

}

if(j & lt;5)

{

pQuest-& gt;boat.wildMan = boatState[j]。懷爾德曼;

pQuest-& gt;boat.churchMan = boatState[j]。教士;

返回TRUE

}

}

返回FALSE

}

Trackback: /TrackBack.aspx?PostId=21630

【點擊此處收藏本文】發表於2004年4月7日下午2:18。

無可奉告。

評論

名稱:

請輸入您的姓名。

網址:

驗證碼

評論

請輸入評論。

記得我嗎?

-

網站介紹-廣告服務-網站地圖-幫助信息-聯系信息-英語-問題報告

CSDN北京安百裏美達美數碼科技有限公司版權所有北京ICP證字第020026號CSDN

2000-04,CSDN.NET,保留所有權利

-

版權?paddy102由。文本