摘要:老師讓用中方式都實現(xiàn)一遍,分別是廣度優(yōu)先搜索深度優(yōu)先搜索和啟發(fā)式搜索。先分享深度優(yōu)先搜索,后兩篇我會分享廣度優(yōu)先搜索和啟發(fā)式搜索的實現(xiàn)。
人工智能課,第一個實驗就是八數碼問題。老師讓用3中方式都實現(xiàn)一遍,分別是廣度優(yōu)先搜索、深度優(yōu)先搜索和啟發(fā)式搜索。心塞╮(╯▽╰)╭。緊急補了一些數據結構的知識,就匆匆上陣。先分享深度優(yōu)先搜索,后兩篇我會分享廣度優(yōu)先搜索和啟發(fā)式搜索的實現(xiàn)。
概念就不講了,百度就行了。簡單說一下我的實現(xiàn):Situation類存儲節(jié)點信息,包括父節(jié)點的code值(code是一個字符串,存儲的是八數碼的狀態(tài),比如“138427056”),當前節(jié)點的code值,以及深度(深度從0開始,即起始節(jié)點深度為0);在Test.cpp的main函數中,我定義了兩個鏈表open和closed分別存放未被擴展的節(jié)點和被擴展的節(jié)點。深度優(yōu)先,新生成的有效的子節(jié)點存放在open表的開頭。每次擴展,拿open表的開頭的那個節(jié)點來擴展,方法是把open表的頭節(jié)點移動到closed表的末端,生成的最多4個有效的子節(jié)點存放在open表的開頭。其他就是比較生成的節(jié)點和目標節(jié)點是否相等了。
以下代碼在win8.1下VS2013中測試成功。
頭文件Deep.h:
#include#include"queue" #include"string" #include using namespace std; const string GOAL = "803214765"; class Situation{ private: public: string father; string code;//當前狀態(tài) int deep; Situation up(); Situation down(); Situation left(); Situation right(); bool isGoal(); bool isInOpen(deque
&open); bool isInClosed(deque &closed); void show() const; void show(string) const; void show_deque(deque &) const; deque showWay(deque &closed); void showAnswer(deque &closed);//顯示解答 Situation() :father(""), code(""), deep(-1){}; };
Deep.cpp:
#include"Deep.h" Situation Situation::up(){ string::size_type loc = code.find("0");//0的位置,從0開始計數 Situation son; son.code = code; son.deep = deep + 1; if (loc>=3){ char temp = son.code[loc];//即0 son.code[loc] = son.code[loc - 3]; son.code[loc-3] = temp; } else{ son.code = ""; } return son; } Situation Situation::down(){ string::size_type loc = code.find("0");//0的位置,從0開始計數 Situation son; son.code = code; son.deep = deep + 1; if (loc<=5){ char temp = son.code[loc];//即0 son.code[loc] = son.code[loc + 3]; son.code[loc + 3] = temp; } else{ son.code = ""; } return son; } Situation Situation::left(){ string::size_type loc = code.find("0");//0的位置,從0開始計數 Situation son; son.code = code; son.deep = deep + 1; if (loc!=0&&loc!=3&&loc!=6){ char temp = son.code[loc];//即0 son.code[loc] = son.code[loc - 1]; son.code[loc - 1] = temp; } else{ son.code = ""; } return son; } Situation Situation::right(){ string::size_type loc = code.find("0");//0的位置,從0開始計數 Situation son; son.code = code; son.deep = deep + 1; if (loc!=2&&loc!=5&&loc!=8){ char temp = son.code[loc];//即0 son.code[loc] = son.code[loc + 1]; son.code[loc + 1] = temp; } else{ son.code = ""; } return son; } bool Situation::isGoal(){ return code == GOAL; } bool Situation::isInOpen(deque&open){ /*deque ::iterator it = open.begin(); while (it != open.end()){ if (code == (*it).code){ return true; } it++; }*/ for (int i = 0; i < open.size();i++){ if (code==open.at(i).code){ return true; } } return false; } bool Situation::isInClosed(deque &closed){ /*deque ::iterator it = closed.begin(); while (it!=closed.end()){ if (code == (*it).code){ return true; } it++; }*/ for (int i = 0; i < closed.size(); i++){ if (code == closed.at(i).code){ return true; } } return false; } void Situation::show() const{ if (!code.empty()){ cout << code[0] << code[1] << code[2] << endl << code[3] << code[4] << code[5] << endl << code[6] << code[7] << code[8] << endl << endl; } else{ cout << "空的" << endl; } } void Situation::show(string code) const{ if (!code.empty()){ cout << code[0] << code[1] << code[2] << endl << code[3] << code[4] << code[5] << endl << code[6] << code[7] << code[8] << endl << endl; } else{ cout << "空的" << endl; } } void Situation::show_deque(deque &m_deque) const{ /*deque ::iterator it = m_deque.begin(); while (it!=m_deque.end()) { (*it).show(); it++; }*/ for (int i = 0; i < m_deque.size();i++){ m_deque.at(i).show(); } } //路徑 deque Situation::showWay(deque &closed){ //cout << closed.size() << endl; deque dequeList; Situation temp = closed.back(); dequeList.push_back(temp); //closed表從后往前,根據father值找到路徑 for (int i = closed.size()-1; i >= 0;i--){ if (temp.father==closed.at(i).code){ dequeList.push_back(closed.at(i)); temp = closed.at(i); } } //cout << dequeList.size() << endl; return dequeList; } void Situation::showAnswer(deque &closed){ deque way(showWay(closed)); cout << "共需要" << way.size() << "步" << endl; for (int i = way.size() - 1; i >= 0; i--) { way.at(i).show(); } //輸出目標 show(GOAL); }
Test.cpp:
#include#include"Deep.h" using namespace std; void loop(deque &open, deque &closed, int range); int main(){ string original = "283164705"; Situation first; deque open, closed;//open存放未擴展節(jié)點,closed存放已擴展節(jié)點 int range = 10;//深度界限 first.code = original; first.deep = 0; open.push_back(first); loop(open,closed,range); return 0; } void loop(deque &open, deque &closed,int range){ Situation a; int i = 0; while (!open.empty()){ cout << i++ << endl; if (open.front().code == GOAL){ cout << "成功:" << endl; a.showAnswer(closed); return; } if (open.empty()){ cout << "失敗" << endl; return; } closed.push_back(open.front()); open.pop_front(); //節(jié)點n的深度是否等于深度界限 if (closed.back().deep == range){ //loop(open,closed,range);不能用遞歸 continue; } else{ //擴展節(jié)點n,把其后裔節(jié)點放入OPEN表的末端 Situation son1 = closed.back().up(); Situation son2 = closed.back().down(); Situation son3 = closed.back().left(); Situation son4 = closed.back().right(); /* 廣度優(yōu)先搜索和深度優(yōu)先搜索的唯一區(qū)別就是子節(jié)點放到open表的位置: (1)廣度優(yōu)先搜索放到open表的后面 (2)深度優(yōu)先搜索放到open表的前面 */ if (!son1.code.empty()){ if (!son1.isInOpen(open)&&!son1.isInClosed(closed)){ son1.father = closed.back().code; open.push_front(son1); } } if (!son2.code.empty()){ if (!son2.isInOpen(open) && !son2.isInClosed(closed)){ son2.father = closed.back().code; open.push_front(son2); } } if (!son3.code.empty()){ if (!son3.isInOpen(open) && !son3.isInClosed(closed)){ son3.father = closed.back().code; open.push_front(son3); } } if (!son4.code.empty()){ if (!son4.isInOpen(open) && !son4.isInClosed(closed)){ son4.father = closed.back().code; open.push_front(son4); } } //是否有任何后繼節(jié)點為目標節(jié)點 if (son1.isGoal()){ cout << "后繼節(jié)點中有目標節(jié)點:" << endl; son1.showAnswer(closed); break; } if (son2.isGoal()){ cout << "后繼節(jié)點中有目標節(jié)點:" << endl; son2.showAnswer(closed); break; } if (son3.isGoal()){ cout << "后繼節(jié)點中有目標節(jié)點:" << endl; son3.showAnswer(closed); break; } if (son4.isGoal()){ cout << "后繼節(jié)點中有目標節(jié)點:" << endl; son4.showAnswer(closed); break; } } } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/19590.html
摘要:寫在最前本次分享一下通過廣度優(yōu)先搜索解決八數碼問題并展示其最短路徑的動畫效果。一個排列中逆序的總數就稱為這個排列的逆序數。如果起始狀態(tài)與結束狀態(tài)的逆序數的奇偶性相同,則說明狀態(tài)可達,反之亦然。 寫在最前 本次分享一下通過廣度優(yōu)先搜索解決八數碼問題并展示其最短路徑的動畫效果。 歡迎關注我的博客,不定期更新中—— 效果預覽 該效果為從[[2, 6, 3],[4, 8, 0],[7, 1, ...
摘要:搜索的概念盲目搜索與啟發(fā)式搜索狀態(tài)空間知識表示法狀態(tài)空間的表示法狀態(tài)空間的圖描述啟發(fā)式圖搜索啟發(fā)式策略運用啟發(fā)式策略的兩種基本情況啟發(fā)信息和估價函數啟發(fā)信息估價函數注意八數碼問題的啟發(fā)函數搜索算法搜索算法及其特性分析可采納性單調性信息性 showImg(https://segmentfault.com/img/remote/1460000017465711);showImg(https...
摘要:它真的是深度優(yōu)先搜索嗎是真的嗎是真的如果是的話,那它的搜索空間解空間是什么是向量組成的集合,而。既然深度優(yōu)先搜索剪枝回溯。 什么是全排列?從n個不同元素中任取m(m≤n)個元素,按照一定的順序排列起來,叫做從n個不同元素中取出m個元素的一個排列。當m=n時所有的排列情況叫全排列。那么ABC的全排列有哪些?根據定義得到:ABCACBBACBCACABCBA 如何通過程序求解?方法一:暴力...
摘要:而此處針對進一步的搜索,有兩個問題需要考慮如何選取搜索起點方格確定哪種搜索策略深度優(yōu)先搜索,廣度優(yōu)先搜索關于第一個問題,無論選擇哪個方格起始搜索,對于能否解決問題來說并不存在差異。 Github倉庫地址 學習是為了尋找解決問題的答案,若脫離了問題只為知曉而進行的打call,那么隨時間流逝所沉淀下來的,估計就只有重在參與的虛幻存在感了,自學的人就更應善于發(fā)現(xiàn)可供解決的問題。為了入門AI,...
閱讀 3257·2021-10-27 14:20
閱讀 2531·2021-10-08 10:05
閱讀 1634·2021-09-09 09:33
閱讀 2906·2019-08-30 13:16
閱讀 1442·2019-08-29 18:34
閱讀 1176·2019-08-29 10:58
閱讀 1231·2019-08-28 18:22
閱讀 1229·2019-08-26 13:33