用MATLAB結合四種方法搜尋羅馬尼亞度假問題

選修了cs的AI課,開始有點不適應,只能用matlab硬著頭皮上了,不過matlab代碼全網僅此一份,倒有點小自豪。

一、練習題目

分別用寬度優先、深度優先、貪婪算法和 A*算法求解“羅馬利亞度假問題”。具體地圖我這里不給出了,有興趣的可以去搜索。即找到從初始地點 Arad到 目的地點 Bucharest 的一條路徑。

要求:分別用文件存儲地圖和啟發函數表,用生成節點數比較以上四種算法在同一問題求解時的效率,列表給出結果。

附:羅馬尼亞度假問題圖(圖1.1)

?

圖1.1 羅馬尼亞度假問題

1.2 題目分析

本題要求分別用寬度優先、深度優先、貪婪算法和 A*算法求解“羅馬利亞度假問題”。羅馬尼亞度假問題本質上屬于“圖類”問題,該地圖上共有20個地點,要求從Arad出發,到達Bucharest,從圖中搜索到達路徑,并比較四種方法的優缺點。因此主要的數據結構可以采用圖存儲的方法,搜索方法題目已經給出。

二、數據結構

2.1 圖結構

圖:由有窮、非空點集和邊集合組成,簡寫成G(V,E),其中,G表示一個圖,V表示圖中的頂點,E表示圖中的邊。在本題,頂點為20個羅馬尼亞城市,邊則為相鄰城市之間的距離。邊之間有方向,圖為有向圖,無方向的圖為無向圖。本題所用的圖為無向圖。

盡管二維數組比較占用內存,但是由于MATLAB對矩陣運算非常方便,運算速度也很快,我采用二維數組的方法存儲鄰接矩陣。對20個地點編號1-20,其中Arad為3號地點,對邊采用數值的方法,例如3號到4號距離為75,則令矩陣中點(3,4)的值為75。并令自身距離為0,不相鄰的點之間也設為0。

2.2 隊列結構

隊列(Queue):是只允許在一端進行插入操作,在另一端進行刪除操作的線性表。隊列也是一種特殊的線性表,是一種先進先出的線性表。允許插入的一端稱為表尾,允許刪除的一端稱為表頭。我們將在廣度優先搜索中使用到這個結構存儲已搜索過的節點。其結構如圖2.2所示。

?

圖2.2 隊列結構圖

2.3 棧結構

棧(Stack):也是一種線性存儲結構,棧中的數據元素遵守“先進后出”(First In Last Out)的原則,簡稱FILO結構。只能在棧頂進行插入和刪除操作。我們將在深度優先搜索中使用到這個結構存儲已搜索過的節點。其結構如圖2.3所示。

?

圖2.3 棧結構圖

三、算法思想

3.1 寬度優先

寬度優先搜索算法(又稱廣度優先搜索)其別名又叫BFS( Breadth First Search)。屬于一種盲目搜尋法,目的是系統地展開并檢查圖中的所有節點,以找尋結果。算法采用隊列的數據結構,所有因為展開節點而得到的子節點都會被加進一個先進先出的隊列中。其鄰居節點尚未被檢驗過的節點會被放置在一個被稱為 open 的隊列,而被檢驗過的節點則被放置在被稱為 closed 的容器中(open-closed表)算法自始至終一直通過已找到和未找到頂點之間的邊界向外擴展,首先搜索和s距離為k的所有頂點,然后再去搜索和S距離為k+l的其他頂點。算法流程圖如圖3.1所示。

?

圖3.1 DFS算法流程圖

3.2 深度優先

深度優先搜索方法,又稱DFS(Depth First Search),和樹的先序遍歷比較類似。假設初始狀態是圖中所有頂點均未被訪問,則從某個頂點v出發,首先訪問該頂點,然后依次從它的各個未被訪問的鄰接點出發深度優先搜索遍歷圖,直至圖中所有和v有路徑相通的頂點都被訪問到。 若此時尚有其他頂點未被訪問到,則另選一個未被訪問的頂點作起始點,重復上述過程,直至圖中所有頂點都被訪問到為止。算法流程圖如圖3.2所示。

?

圖3.2 BFS算法流程圖

3.3 貪婪方法

貪婪算法(又稱貪心算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。為了解決問題,需要尋找一個構成解的候選對象集合,起初,算法選出的候選對象的集合為空。接下來的每一步中,根據選擇函數,算法從剩余候選對象中選出最有希望構成解的對象。如果集合中加上該對象后不可行,那么該對象就被丟棄并不再考慮;否則就加到集合里。每一次都擴充集合,并檢查該集合是否構成解。

本題中具體實現方法為,先進行深度搜索,但是不急進入堆棧操作,而是存儲當前所有搜索到的點的距離,選擇距離最短的點,并放棄搜索其他同一深度的點,進入堆棧操作。算法流程圖如圖3.3所示。

?

圖3.3 貪婪算法流程圖

3.4 A*方法

A*搜尋算法俗稱A星算法。A*算法是比較流行的啟發式搜索算法之一,被廣泛應用于路徑優化領域。它的獨特之處是檢查最短路徑中每個可能的節點時引入了全局信息,對當前節點距終點的距離做出估計,并作為評價該節點處于最短路線上的可能性的量度。

本題中的實現方法為,同貪婪類似,A*就相當于有一個智慧的老人為搜尋的對象打分,搜索過程中將距離和打分值相加,作為新的距離即可。其算法流程圖如3.4所示。

?

圖3.3 A*算法流程圖

四、關鍵代碼

4.1 BFS方法

while tail~=head              %判斷
i=queue(tail);               %取點for j=1:20              %搜索所有適合的節點if A(i,j)>=1 && isempty(find(flag==j,1))queue(head)=j;                        head=head+1;                  %數數         flag=[flag j];                %擴容        result=[result;i,j,A(i,j)];                  %記錄endendtail=tail+1;                 %隊列增加
end

  

?

4.2 DFS方法

while top~=0            %判斷
pre_len=length(stack);    %記錄棧長度i=stack(top);             %取棧頂for j=1:20if A(i,j)>=1 && isempty(find(flag==j,1))   top=top+1;                         stack(top)=j;                      flag=[flag j];                     re=[re;i,j,A(i,j)];                             %記錄           
       break; endend if length(stack)==pre_len %如果棧未增加,則出棧stack(top)=[];top=top-1;end end

4.3 貪婪方法

while top~=0           pre_len=length(stack);   i=stack(top);          record=[];                for j=1:20if A(i,j)>=1 && isempty(find(flag==j,1))    %記錄所有相鄰節點record=[record;i,j,A(i,j)]    endendif isempty(record)breakend[s,k]= min(record(:,3,:))              %取距離最小節點i=record(k,1,:);j=record(k,2,:);     if isempty(find(flag==j,1))top=top+1;                        stack(top)=j;                      flag=[flag j];                     re=[re;i,j,A(i,j)];                            endif length(stack)==pre_len  stack(top)=[];top=top-1;end   
end

  

4.4 A*方法

絕大部分與貪婪算法相同,只是更新了距離值。

for j=1:20if A(i,j)>=1 && isempty(find(flag==j,1))     F(i,j)=A(i,j)+H(j);record=[record;i,j,F(i,j)];    %啟發值endendif isempty(record)break
end

  

4.5 反向尋址

所有的算法均采用相同的反向尋址方法。

while (1)x=find(re(:,2,:)==m)       %找到到達目的地所有的經過地m=re(x,1,:)                  %迭代法反向尋找來的路徑if  1-isempty(x)lujin=[city{re(x,1,:)},lujin];juli=juli+re(x,3,:)elsebreak
end
end    

  

4.6 讀取EXCEL

city={'Oradea','Zerind','Arad','Timisonra','Lugoj','Mehadia','Dobreta','Craiova','Rimmicu Vikea','Sibiu',...'Fagaras','Pitesti','Bucharest','Giurglu','Uiziceni','Hirsova','Eforie','Vaslui','Lasi','Neamt'};         %存儲城市名
filename = 'mymap.xlsx';
sheet = 1;
xlRange = 'C3:V22';
map = xlsread(filename,sheet,xlRange);       %讀取excel
map(isnan(map)) = 0;                   %將不相鄰的點之間也設為0

  

五、運行結果

BFS方法的運行結果顯示路徑為:{'Arad'??? 'Sibiu'??? 'Fagaras'??? 'Bucharest'}

DFS方法的運行結果顯示路徑為:{ 'Arad'??? 'Zerind'??? 'Oradea'??? 'Sibiu'??? 'Rimmicu Vikea'??? 'Craiova'??? 'Pitesti'??? 'Bucharest'}

貪婪方法的運行結果顯示路徑為:{ 'Arad'??? 'Zerind'??? 'Oradea'??? 'Sibiu'??? 'Rimmicu Vikea'??? 'Pitesti'??? 'Bucharest'}

A*方法的運行結果顯示路徑為:{ 'Arad'??? 'Sibiu'??? 'Rimmicu Vikea'??? 'Pitesti'??? 'Bucharest'}

比較見表5.1

表5.1 四種算法的運行結果

算法

生成節點數

求解時間

距離

BFS方法

11

3.725s

450

DFS方法

12

3.057s

762

貪婪方法

7

3.606s

575

A*方法

7

3.049s

418

注:求解時間包括計時函數自用時間

六、比較結論

得益于MATLAB高速的矩陣運算能力,四種方法均在3-4秒之間完成,速度相差不大,但是在生成節點數上,DFS方法搜索了12個節點最多,貪婪方法和A*方法均為7最少。比較四種搜索方法得到的搜索路徑,有啟發值的A*方法搜索到的路徑距離最短,為418,其次是寬度優先搜索,距離為450,距離最長的路徑是由DFS方法產生,為762,貪婪方法為575。通過比較我們可以得出如下結論:

  1. 四種搜索方法在處理小型網絡的搜索問題時,速度相差不大。
  2. 貪婪方法和A*方法生成節點數較少,理論上能夠更快搜索出到達路徑,在處理大型圖的問題時,會表現得比較明顯。
  3. 貪婪方法每一步都是選擇當前狀態下的最優解進行搜索,很容易陷入局部最優,從而使得搜索時間延長。
  4. 盡管BFS方法和DFS方法都一定可以找到路徑,但是BFS方法搜索到的路徑距離要明顯優于DFS方法。

?

---恢復內容結束---

轉載于:https://www.cnblogs.com/Hangingter/p/7784042.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/540372.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/540372.shtml
英文地址,請注明出處:http://en.pswp.cn/news/540372.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[轉載] Java中文與ASCII碼的轉換

參考鏈接: 擴展Java中的原始轉換 今天在研究Java中編碼的時候,看到了Java中ascii碼的強大。寫了一個CoderUtils.java,以后會擴展它。 package com.xingxd.study.test; import java.io.File; import java.io.FileWriter; import java.io.I…

[轉]Paul Adams:為社交設計

為社交設計 Strong, Weak, and Temporary Ties by Paul Adams on 2010/04/09 PS:作者Paul Adams Facebook全球品牌體驗總監 電話和手機聚集十億用戶用了15年的時間,而Facebook只用了9個月。我們看到越來越多的人開始用在線社交網絡,這種網絡好…

[轉載] Java中日期格式轉換

參考鏈接&#xff1a; Java中的類型轉換和示例 Code: /** * 字符串轉換為java.util.Date<br> * 支持格式為 yyyy.MM.dd G at hh:mm:ss z 如 2002-1-1 AD at 22:10:59 PSD<br> * yy/MM/dd HH:mm:ss 如 2002/1/1 17:55:00<br> * yy/MM/dd HH:…

Android Framework中的Application Framework層介紹

Android的四層架構相比大家都很清楚&#xff0c;老生常談的說一下分別為&#xff1a; Linux2.6內核層&#xff0c;核心庫層&#xff0c;應用框架層&#xff0c;應用層。我今天重點介紹一下應用框架層Framework。 Framework層為我們開發應用程序提供了非常多的API&#xff0c;我…

[轉載] java注釋

參考鏈接&#xff1a; Java注釋 Java注釋 java中注釋有三種&#xff1a;這些都稱之為java doc標記&#xff0c;含義如下&#xff1a; java中注釋有三種&#xff1a; 單行注釋 //注釋的內容&#xff0c;多行注釋 /…注釋的內容…/&#xff0c;文檔注釋 /**…注釋的內容….*/。…

環路是怎樣形成的實例

環路是怎樣形成的一個由十多臺交換機組成的小型局域網&#xff0c;交換機大多是Cisco的中低端系列產品。某日突然出現問題&#xff1a;局域網內的主機之間相互ping時&#xff0c;都出現延時長、丟包現象&#xff0c;網絡應用奇慢無比。 觀察交換機設備&#xff0c;指示燈看不出…

[轉載] 《Python語言程序設計》課程筆記

參考鏈接&#xff1a; Python程式設計語言 文章目錄 第一部分 Python快速入門第1周 Python基本語法元素第2周 Python基本圖形繪制 第二部分 Python基礎語法第3周 基本數據類型3.1 數字類型及操作3.3 字符串類型及操作3.4 模塊2: time庫的使用 第4周 程序的控制結構4.1 程序的分…

ORACLE中創建如何創建表,并設置結構和默認值

使用select語句查看EMP表&#xff0c;根據COMM排序 默認情況下&#xff0c;空值會自動排列在尾部。 利用nulls last排序時將空值置底 利用nulls first排序時將空值置頂 例 創建一張出版社表 使用語句 create table 表名&#xff08;列名1 類型&#xff0c;列名2 類型&#xff0…

[轉載] C++靈魂所在之---多態的前世與今生

參考鏈接&#xff1a; Java是否支持goto 開頭先送大家一句話吧&#xff1a; 眾所周知&#xff0c;在20世紀80年代早期&#xff0c;C在貝爾實驗室誕生了&#xff0c;這是一門面向對象的語言&#xff0c;但它又不是全新的面向對象的語言&#xff0c;它是在傳統的語言…

Code Sinppet

如果你在使用VS 2005,如果你不能使用它的Code Snippet功能&#xff0c;如果你在實現抽象類override 方法時彈出&#xff1a;Code Snippet titled [Method Stub - Body] failed to load. Verify that refactoring snippets are recognized in the Code Snippet Manager and that…

暴風TV請來中國人工智能first lady馮雁教授任首席科學家

今日下午&#xff0c;暴風AI無屏電視發布會現場&#xff0c;暴風TV宣布邀請號稱“中國人工智能first lady”、于香港科技大學任教的馮雁教授&#xff0c;擔任暴風TV人工智能首席科學顧問。 馮雁教授于現場表示&#xff0c;選擇暴風TV合作的重要原因&#xff0c;一方面在于其個人…

[轉載] java 計算協方差_Java的深度:通過協方差暴露的API泄漏

參考鏈接&#xff1a; 關于Java中null的有趣事實 java 計算協方差 Java有時可能非常棘手&#xff0c;特別是在API設計中。 讓我們看一個非常有趣的展示柜。 jOOQ強烈地將API與實現分開。 所有API都在org.jooq包中&#xff0c;并且是公共的。 大多數實現是在org.jooq.impl包…

gulp之gulp.watch報錯

gulpfile.js如下&#xff1a; 問題&#xff1a; 第一次改動文件&#xff0c;監聽正常。再次改動&#xff0c;報錯&#xff0c;如下&#xff1a; 解決&#xff1a; 總結&#xff1a; 意思&#xff0c;gulpsequence這玩意兒返回的thunk只能執行一次 轉載于:https://www.cnblogs.c…

[轉載] mybatis

參考鏈接&#xff1a; 在Java中使用_(下劃線)作為變量名 mybatis第一天 1.mybatis概述和環境搭建 mybatis概述 mybatis環境搭建 1. 創建maven工程、添加開發依賴、創建數據庫和表&#xff1b; 2. 創建domain實體類和dao mybatis是一門java語言編寫持久層框架…

設置了li(float:right),里面的li反過來顯示 - 解決辦法

設置了li(float:right),里面的li反過來顯示 - 解決辦法 可以讓ul float:right ul里的li 依然float:left 本文轉自許琴 51CTO博客&#xff0c;原文鏈接&#xff1a;http://blog.51cto.com/xuqin/1127540&#xff0c;如需轉載請自行聯系原作者

[轉載] 純函數和函數柯里化

參考鏈接&#xff1a; 用示例編寫Java柯里化Currying函數 文章目錄 純函數什么是純函數純函數例子非純函數例子 函數柯里化函數柯里化簡單例子參數復用 純函數 什么是純函數 如果函數的調用參數相同&#xff0c;則永遠返回相同的結果。它不依賴于程序執行期間函數外部任何狀…

[轉載] scala

參考鏈接&#xff1a; 在Java的數字中使用下劃線 1 scala 底層是有一種隱式轉換機制&#xff0c;比如對String類型&#xff0c;底層會轉化Scala的StringOps類型 2 scala 的通用的化簡規則&#xff1a;調方法時候&#xff0c;方法的參數列表只有一個&#xff0c;則方法的&…

MySQL數據庫學習筆記

MySQL常用語法總結 一.創建Web數據庫 1.登陸到數據庫 mysql -h hostname -u username -p mysql -h hostname -u username -D dbname -p 2.創建數據庫 CREATE database dbname 3.使用數據庫 USE dbname 4.創建數據庫表 CREATE TABLE tablename (columns) 5.列的數據 create tabl…

[轉載] java實現四種常用排序算法

參考鏈接&#xff1a; 用Java排序 四種常用排序算法 ##注&#xff1a;從小到大排 ##冒泡排序## 特點&#xff1a;效率低&#xff0c;實現簡單 思想&#xff1a;每一趟將待排序序列中最大元素移到最后&#xff0c;剩下的為新的待排序序列&#xff0c;重復上述步驟直到排完所…

[轉載] Java復制對象與集合工具類

參考鏈接&#xff1a; Java中的類和對象 項目中經常需要將某個對象的屬性值復制給另一個對象&#xff0c;或者將一個集合復制到另一個集合。利用spring提供的BeanUtils&#xff0c;自己簡單封裝了一個工具類。 public class CopyUtils { /** * 復制集合 */ public static &l…