ACM搜索算法總結

轉自:http://blog.csdn.net/shenmen123456/article/details/6695499 在此感謝~

搜索是ACM競賽中的常見算法,本文的主要內容就是分析它的 特點,以及在實際問題中如何合理的選擇搜索方法,提高效率。文章的第一部分首先分析了各種基本的搜索及其各自的特點。第二部分在基本搜索方法的基礎上提出 一些更高級的搜索,提高搜索的效率。第三部分將搜索和動態規劃結合,高效地解決實際問題,體現搜索的廣泛應用性。第四部分總結全文。


文章在分析各種搜索的同時,分析了我們在解題中應該怎樣合理利用它,理論結合實際,對我們的解題實踐有一定的指導意義。

【 Abstract 】 Search is a algorithm which is often seen in ACM/ICPC .The main idea of this article is to analysis its specially characterist and how to choose search method reasonably for the increasing efficiency in practical problems.

The first section analysis every basic search method and each specially characterist. The second section bring up some advanced search methods to increase the efficiency.The third section is to combine the search method and dynamic programing method to solve practical problem efficiencily indicating that search methods have weed applicability.The fourth section is to sum up the article and prospect the development of search.

提起搜索,大家都不會陌生。它的應用是十分廣泛的,比如目前internet上的搜索引擎,WINDOWS XP操作系統中的文件搜索。同時,搜索是編程解題的一種重要的手段,在競賽中,我們有時會碰到一些題目,它們既不能通過建立數學模型解決,又沒有現成算法 可以套用,或者非遍歷所有狀況纔可以得出正確結果。這時,我們就必須採用搜索算法來解決問題。幾乎每次ACM競賽都要考察到這方面的內容。因此,如何更深 入地瞭解搜索,從而更爲有效地運用這個解題的有力武器,是一個值得深入研究的問題。要掌握搜索的應用技巧,就要了解它的分類及其各方面的特點。

第一部分 基本的搜索算法
一、回溯算法
回溯算法是所有搜索算法中最爲基本的一種算法,其採用了一種“走不通就掉頭”思想作爲其控制結構,其相當於採用了先根遍歷的方法來構造解答樹,可用於找解或所有解以及最優解。

評價:回溯算法對空間的消耗較少,當其與分枝定界法一起使用時,對於所求解在解答樹中層較深的問題 有較好的效果。但應避免在後繼節點可能與前繼節點相同的問題中使用,以免產生循環。

二、深度搜索與廣度搜索
深度搜索與廣度搜索的控制結構和產生系統很相似,唯一的區別在於對擴展節點選取上。由於其保留了所有的前繼節點,所以在產生後繼節點時可以去掉一部分重複 的節點,從而提高了搜索效率。這兩種算法每次都擴展一個節點的所有子節點,而不同的是,深度搜索下一次擴展的是本次擴展出來的子節點中的一個,而廣度搜索 擴展的則是本次擴展的節點的兄弟節點。在具體實現上爲了提高效率,所以採用了不同的數據結構.

評價:廣度搜索是求解最優解的一種較好的方法,在後面將會對其進行進一步的優化。而深度搜索多用於只要求解,並且解答樹中的重複節點較多並且重複較難判斷時使用,但往往可以用A*或回溯算法代替。

第二部分 搜索算法的優化(一)
一、雙向廣度搜索
廣度搜索雖然可以得到最優解,但是其空間消耗增長太快。但如果從正反兩個方向進行廣度搜索,理想情況下可以減少二分之一的搜索量,從而提高搜索速度。

二、分支定界
分支定界實際上是A*算法的一種雛形,其對於每個擴展出來的節點給出一個預期值,如果這個預期值不如當前已經搜索出來的結果好的話,則將這個節點(包括其子節點)從解答樹中刪去,從而達到加快搜索速度的目的。

三、A*算法
A*算法中更一般的引入了一個估價函數f,其定義爲f=g+h。其中g爲到達當前節點的耗費,而h表示對從當前節點到達目標節點的耗費的估計。其必須滿足兩個條件:

1. h必須小於等於實際的從當前節點到達目標節點的最小耗費h*。
2. f必須保持單調遞增。

A*算法的控制結構與廣度搜索的十分類似,只是每次擴展的都是當前待擴展節點中f值最小的一個,如果擴展出來的節點與已擴展的節點重複,則刪去這個節點。如果與待擴展節點重複,如果這個節點的估價函數值較小,則用其代替原待擴展節點。

對A*算法的改進–分階段A*. 當A*算法出現數據溢出時,從待擴展節點中取出若干個估價函數值較小的節點,然後放棄其餘的待擴展節點,從而可以使搜索進一步的進行下去。

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

下面,以一個具體的實例來分析比較上述幾種搜索算法的效率等問題。

在scu online judge(http://cs.scu.edu.cn/acm)上有這麼一道題目:這就是古老而又經典的15數碼難題:在4*4的棋盤上,擺有15個棋 子,每個棋子分別標有1-15的某一個數字。棋盤中有一個空格,空格周圍的棋子可以移到空格中。現給出初始狀態和目標狀態,要求找到一種移動步驟最少的方 法。

看到這個題目,會發覺幾乎每個搜索算法都可以解這個問題。而事實確實如此。

首先考慮深度優先搜索,它會遍歷這棵解答樹。這棵解答樹最多可達16!個節點,深度優先搜索必須全部遍歷後,才能從所有解中選出最小的一個做爲答案,其代價是非常巨大的。

其次考慮廣度深度優先搜索,這不失爲一個好辦法。因爲廣度優先搜索的層次遍歷解答樹的特點,一旦搜索到一個目標節點,那麼這時的深度一定是最優解,而不必 象深度優先搜索那樣繼續搜索目標節點,最後比較才能得出最優解。該搜索方法在這道題目上會遇見致命的問題:廣度深度優先搜索是一種盲目的搜索,深度比較大 的測試數據會產生大量的無用的節點,同時消耗很多時間在重複節點的判斷上。

爲了減少重複的節點,加入人工智能性,馬上可以想到用A*算法。經過分析發現,該方法對避免產生大量的無用的節點起到了一定的效果,但是會花97%以上的 時間去判斷新產生節點是否與已擴展的和待擴展的節點重複。看來如何提高判重的速度成爲該題目的關鍵。解決這個問題有很多辦法,比如引入哈希表,對已擴展的 和待擴展的節點採用哈希表存儲,減少判重的代價,或者對已擴展的和待擴展的節點採用桶排序,也可以減少判重的代價。我們現在來嘗試一下用 IDA*算法。該算法有個值得注意的地方:對估計函數的選取。如果選用當前狀態每個位置上與目標狀態每個位置上相同節點的數目加當前狀態的深度作爲估計函 數,由於當前狀態每個位置上與目標狀態每個位置上相同節點的數目這個值一般較小,不能明顯顯示各個狀態之間的差別,運行過程中會產生大量的無用的節點,同 樣會使效率很低,不能在60s以內完成計算。比較優化的一個辦法是選用由於當前狀態每個位置上的數字偏離目標節點該數字的位置的距離加當前狀態的深度作爲 估計函數。這個估計函數的選取沒有統一的標準,找到合適的該函數並不容易,但是可以大致按照這個原則:在一定範圍內加大各個狀態啓發函數值的差別。

實踐證明,該方法用廣泛的通用性,在很多情況下可以替換一般的深度優先搜索和廣度優先搜索。

第三部分 搜索算法的優化(二)
該部分將談到搜索與其他算法的結合。再看scu online judge的一道題目: 給定一個8 * 8的國際象棋棋盤。給出棋盤上任意兩個位置的座標,問馬最少幾步可以從一個位置跳到另外一個位置。(POJ1915類似)

該題目同樣是求最優解,如果用一般的深度優先搜索是很容易超時的。如果用廣度優先搜索,會消耗大量的內存,而且效率是很低的。這裏,我們將嘗試用深度優先搜索加動態規劃的算法解決該問題。

將該棋盤做爲存儲狀態的矩陣。每個矩陣元素的值是該位置到初始位置最少需要的步數。初始位置的元素值爲0。其他位置的元素初始化爲一個很大的正整數。首先 從初始位置開始深度優先搜索,例如某次從(i1,j1)到達位置(i2,j2),如果(i2,j2)處的值大於(i1,j1)的值加1,則(i2,j2) 處的值更新爲(i1,j1)+ 1,表示從(i1,j1) 跳到(i2,j2)比從其他地方跳到(i2,j2)更優,不斷的進行這個過程,直到不能進行下去位置,那麼最後的目標位置的值就是解。這就是一個動態規劃 的思想,每個位置的最優解都是由其他能夠一次跳到這個位置的位置的值決定的,而且是它們中的最小值。同時,該動態規劃又藉助深度優先搜索這個工具,完成對 每個位置的值的刷新,可以算是一個比較經典的深度優先搜索和動態規劃的結合。該問題還需要注意一個剪枝的問題,從起始位置到目標位置的最大步數是多少?經 過計算,最大值是6。所以一旦某個位置的值是6了,就不必再將它去刷新另外的位置,從而剪去了對很多不必要子樹的搜索,大大提高了效率。

第四部分結語
本文的主要的篇幅講的都是理論,但是根本的目的還是指導實踐。搜索,據我認爲,是當今ACM競賽中最常規、也最能體現解題者水平的一類解題方法。 “紙上得來終覺淺,絕知此事要躬行。”要想真正領悟、理解各種搜索的思想,掌握搜索的解題技巧,還需要在實踐中不斷地挖掘、探索。實踐得多了,也就能體會 到漸入佳境之妙了。算法的優化是無窮盡的。
        </div>
            </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章