目錄
一、八數碼難題
1. 需求分析
2. 數據結構、功能模塊設計與說明
2.1 算法思路
2.2 數據結構
3. 核心代碼與測試結果說明
3.1 核心代碼
3.2 測試結果說明
4.?存在的問題與體會
4.1 存在的問題
4.2 體會
二、傳教士與野人渡河
1. 需求分析
2. 數據結構、功能模塊設計與說明
2.1 算法思路
2.2 數據結構
3. 核心代碼與測試結果說明
3.1 核心代碼
3.2 運行結果
引言:借助產生式系統和狀態空間法,選擇一種編程語言(我用的是java),完成題目要求。
一、八數碼難題
在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有一個空格,空格可用0來表示。空格周圍的棋子可以移到空格中。要求解的問題是:給出一種初始布局(初始狀態)和目標布局,找到一種移動方法,實現從初始布局到目標布局的轉變。
1. 需求分析
在一個3×3的棋盤格中,擺有1-8數字的八個棋子,剩余的空格用0表示。給出一種初始布局和目標布局,找到一種移動方法,實現從初始布局到目標布局的轉變,規則是移動空格,并且空格不能移出棋盤外。
2. 數據結構、功能模塊設計與說明
2.1 算法思路
采用廣度優先搜索算法,從初始狀態開始,每次進行可行操作(與0所在位置相鄰數字交換),得到新的狀態,并將其加入隊列中,直到找到目標狀態為止。
在搜索之前需要判斷一下目標狀態是否可達,根據八數碼問題的特性,合法的移動操作只涉及兩個數字的交換,空格左右移動不會改變任何兩對數字之間的逆序對數量,因為整個序列的相對順序保持不變。空格上下移動會改變兩對數字之間的逆序對數量。當初始狀態的空白格和目標狀態的空白格在不同行時,只有通過上下移動才有可能改變逆序對的數量,從而實現初始狀態到目標狀態的轉換。故當初始狀態和結果狀態逆序數奇偶性相同的時候才可達,否則不進行搜索。
當目標狀態可達的時候,又因為有很多狀態會重復出現,所以判斷移動之后的狀態是否出現過?這里用哈希表來去重,如果出現過則丟棄;否則,將它加入隊列,并將它對應的步數設為前一個狀態的步數+1,直到找到目標狀態為止。
2.2 數據結構
(1)Scanner:用于從控制臺讀取輸入。
(2)HashMap:用于存儲狀態路徑信息和去重,其中鍵是狀態的字符串表示,值是一個 State 對象,包含了上一個狀態的字符串、到達當前狀態的操作和已經移動的步數。
(3)隊列:用于實現廣度優先搜索算法,使用 LinkedList 類作為隊列的實現。
(4)StringBuffer:創建一個 StringBuffer 對象,調用其 setCharAt() 方法進行字符交換。
3. 核心代碼與測試結果說明
3.1 核心代碼
(1)初始化狀態
(2)判斷可達性
①求逆序對
②判斷初始布局和結束布局奇偶性是否相同
(3)哈希表
(4)隊列實現bfs
3.2 測試結果說明
(1)測試數據
(2)控制臺打印每一步的狀態和操作
4.?存在的問題與體會
4.1 存在的問題
這種解法空間復雜度較高。使用廣度優先搜索算法時,需要存儲所有的狀態和路徑信息。通過哈希表來存儲狀態路徑信息,可能會占用較大內存空間,特別是當搜索空間非常龐大時。所以可以考慮使用其他數據結構或優化算法,以減少空間復雜度。
4.2 體會
雖然代碼存在一些問題和可以改進的地方,但我深入理解了廣度優先搜索算法,并在實踐中獲得了關于數據結構和代碼設計的經驗。
二、傳教士與野人渡河
設有3個傳教士和3個野人來到河邊,打算乘一只船從右岸渡到左岸去。該船每一次只能裝載2人。在任何時候,如果野人人數超過傳教士人數,那么野人就會把傳教士吃掉。請你設計一個方案怎樣才能用這條船安全地把所有人都渡過河去?編程實現你的方案。
1. 需求分析
有3個傳教士和3個野人從河右岸乘一只船到左岸,且該船每次只能裝載2人。必須保證在任何時候,野人人數不能超過傳教士人數,否則野人就會把傳教士吃掉。設計一個方案怎樣才能用這條船安全地把所有人都渡過河去?并且推廣到有n個傳教士和n個野人,河邊的船每次至多可供k個人渡河的解決方案。
2. 數據結構、功能模塊設計與說明
2.1 算法思路
使用深度優先搜索算法,尋找所有可能的移動方案。其中,每個狀態包括左岸傳教士和野人的數量,以及船的位置(左岸或右岸)。通過不斷嘗試不同的移動方案,最終找到一種能夠使所有人都安全到達右岸的方法。
2.2 數據結構
(1)自定義屬性如下
(2)設計State類,屬性如下
(3)用list記錄路徑
(4)存儲可枚舉的方法
3. 核心代碼與測試結果說明
3.1 核心代碼
(1)初始化數據
(2)列出可枚舉的方法,即不同人數的乘客在船上的組合方式。
(3)過河問題的狀態
(4)dfs算法
3.2 運行結果
4. 存在的問題與體會
更加深刻的理解了dfs算法,以及它在實際情況中的應用。