1. 程式人生 > >如果這是你所愛的,要堅持,並踏實。

如果這是你所愛的,要堅持,並踏實。

今天學習了IDA*演算法,在這裡總結一下:

IDA*演算法是A*演算法和迭代加深演算法的結合。

迭代加深演算法是在dfs搜尋演算法的基礎上逐步加深搜尋的深度,它避免了廣度優先搜尋佔用搜尋空間太大的缺點,也減少了深度優先搜尋的盲目性。它主要是在遞迴搜尋函式的開頭判斷當前搜尋的深度是否大於預定義的最大搜索深度,如果大於,就退出這一層的搜尋,如果不大於,就繼續進行搜尋。這樣最終獲得的解必然是最優解。

而在A*演算法中,我們通過使用合理的估價函式,然後在獲得的子節點中選擇fCost最小的節點進行擴充套件,以此完成搜尋最優解的目的。但是A*演算法中,需要維護關閉列表和開放列表,需要對擴展出來的節點進行檢測,忽略已經進入到關閉列表中的節點(也就是所謂的“已經檢測過的節點”),另外也要檢測是否與待擴充套件的節點重複,如果重複進行相應的更新操作。所以A*演算法主要的代價花在了狀態檢測和選擇代價最小節點的排序上,這個過程中佔用的記憶體是比較大的,一般為了提高效率都是使用hash進行重複狀態檢測。

而IDA*演算法具有如下的特點:(

綜合了A*演算法的人工智慧性和回溯法對空間的消耗較少的優點,在一些規模很大的搜尋問題中會起意想不到的效果。它的具體名稱是 Iterative Deepening A*, 1985年由Korf提出。該演算法的最初目的是為了利用深度搜索的優勢解決廣度A*的空間問題,其代價是會產生重複搜尋。歸納一下,IDA*的基本思路是:首先將初始狀態結點的H值設為閾值maxH,然後進行深度優先搜尋,搜尋過程中忽略所有H值大於maxH的結點;如果沒有找到解,則加大閾值maxH,再重複上述搜尋,直到找到一個解。在保證H值的計算滿足A*演算法的要求下,可以證明找到的這個解一定是最優解。在程式實現上,IDA* 要比 A* 方便,因為不需要儲存結點,不需要判重複,也不需要根據 H值對結點排序,佔用空間小


而這裡在IDA*演算法中也使用合適的估價函式,來評估與目標狀態的距離。

在一般的問題中是這樣使用IDA*演算法的,當前局面的估價函式值+當前的搜尋深度 > 預定義的最大搜索深度時,就進行剪枝。

這個估計函式的選取沒有統一的標準,找到合適的該函式並不容易,但是可以大致按照這個原則:在一定範圍內加大各個狀態啟發函式值的差別

下面是poj2286 the rotation game的一道題目,使用了IDA*演算法:

 

有空找一下錯誤,發現錯誤的哥們可以給我留個言:(ps:錯誤解決了,在IDA*演算法的遞迴呼叫if語句為true時,應該返回的是true,而不是false)。

下面是一道自己做的poj2870的搜尋題,在這道題中,我也使用了IDA*演算法來剪枝,比起純粹的dfs,效果還是很明顯的。

在這裡我總結一下IDA*搜尋演算法的一些注意點:

1、IDA*演算法中,main函式一般使用逐步加大搜索深度來獲得最優解,而如果使用dfs搜尋策略的話,就需要對整個搜尋空間進行搜尋,在搜尋函式中判斷出所有合法解中的最優解(通過比較合法解的深度,選擇深度最小的,其實在bfs搜尋中,深度對應的就是題目中所要求的最優解量)

2、在IDA*的搜尋核心演算法中,前半部分就是剪枝,返回false的情況,這點和dfs是一樣的。而在常規的搜尋中,當找到最優解時,就返回true,而當後面的if語句中的dfs遞迴為true時,返回true,如此退出整個迴圈,否則會死迴圈。為了提高效率,可以把當前狀態拷貝到臨時狀態,然後使用臨時狀態進行遞迴搜尋,這樣就不需要在遞迴函式返回時,還原原來的整個狀態。

另外可以看到通過下面的程式碼中新增適當的語句就可以還原出整個最優解的路徑: