经典算法总结
最近公司做編程比賽,力扣上選題,題庫714,初看題覺得還是有難度的,有人說4行代碼解決這個問題,勾起了對這個問題的研究,同時也明白算法的力量。
-
分治算法
-
動態(tài)規(guī)劃算法
-
貪心算法
-
分支限界法
-
回溯法
動態(tài)規(guī)劃算法
一、基本概念
?? ?動態(tài)規(guī)劃過程是:每次決策依賴于當(dāng)前狀態(tài),又隨即引起狀態(tài)的轉(zhuǎn)移。一個決策序列就是在變化的狀態(tài)中產(chǎn)生出來的,所以,這種多階段最優(yōu)化決策解決問題的過程就稱為動態(tài)規(guī)劃。
二、基本思想與策略
?? ?基本思想與分治法類似,也是將待求解的問題分解為若干個子問題(階段),按順序求解子階段,前一子問題的解,為后一子問題的求解提供了有用的信息。在求解任一子問題時,列出各種可能的局部解,通過決策保留那些有可能達到最優(yōu)的局部解,丟棄其他局部解。依次解決各子問題,最后一個子問題就是初始問題的解。
?? ?由于動態(tài)規(guī)劃解決的問題多數(shù)有重疊子問題這個特點,為減少重復(fù)計算,對每一個子問題只解一次,將其不同階段的不同狀態(tài)保存在一個二維數(shù)組中。
?? ?與分治法最大的差別是:適合于用動態(tài)規(guī)劃法求解的問題,經(jīng)分解后得到的子問題往往不是互相獨立的(即下一個子階段的求解是建立在上一個子階段的解的基礎(chǔ)上,進行進一步的求解)。
三、適用的情況
能采用動態(tài)規(guī)劃求解的問題的一般要具有3個性質(zhì):
??? (1) 最優(yōu)化原理:如果問題的最優(yōu)解所包含的子問題的解也是最優(yōu)的,就稱該問題具有最優(yōu)子結(jié)構(gòu),即滿足最優(yōu)化原理。
??? (2) 無后效性:即某階段狀態(tài)一旦確定,就不受這個狀態(tài)以后決策的影響。也就是說,某狀態(tài)以后的過程不會影響以前的狀態(tài),只與當(dāng)前狀態(tài)有關(guān)。
?? (3)有重疊子問題:即子問題之間是不獨立的,一個子問題在下一階段決策中可能被多次使用到。(該性質(zhì)并不是動態(tài)規(guī)劃適用的必要條件,但是如果沒有這條性質(zhì),動態(tài)規(guī)劃算法同其他算法相比就不具備優(yōu)勢)
四、求解的基本步驟
?? ??動態(tài)規(guī)劃所處理的問題是一個多階段決策問題,一般由初始狀態(tài)開始,通過對中間階段決策的選擇,達到結(jié)束狀態(tài)。這些決策形成了一個決策序列,同時確定了完成整個過程的一條活動路線(通常是求最優(yōu)的活動路線)。如圖所示。動態(tài)規(guī)劃的設(shè)計都有著一定的模式,一般要經(jīng)歷以下幾個步驟。
????初始狀態(tài)→│決策1│→│決策2│→…→│決策n│→結(jié)束狀態(tài)
?? ? ? ? ? ? ? ? ? ? ?圖1 動態(tài)規(guī)劃決策過程示意圖
??? (1)劃分階段:按照問題的時間或空間特征,把問題分為若干個階段。在劃分階段時,注意劃分后的階段一定要是有序的或者是可排序的,否則問題就無法求解。
??? (2)確定狀態(tài)和狀態(tài)變量:將問題發(fā)展到各個階段時所處于的各種客觀情況用不同的狀態(tài)表示出來。當(dāng)然,狀態(tài)的選擇要滿足無后效性。
??? (3)確定決策并寫出狀態(tài)轉(zhuǎn)移方程:因為決策和狀態(tài)轉(zhuǎn)移有著天然的聯(lián)系,狀態(tài)轉(zhuǎn)移就是根據(jù)上一階段的狀態(tài)和決策來導(dǎo)出本階段的狀態(tài)。所以如果確定了決策,狀態(tài)轉(zhuǎn)移方程也就可寫出。但事實上常常是反過來做,根據(jù)相鄰兩個階段的狀態(tài)之間的關(guān)系來確定決策方法和狀態(tài)轉(zhuǎn)移方程。
??? (4)尋找邊界條件:給出的狀態(tài)轉(zhuǎn)移方程是一個遞推式,需要一個遞推的終止條件或邊界條件。
?? ?一般,只要解決問題的階段、狀態(tài)和狀態(tài)轉(zhuǎn)移決策確定了,就可以寫出狀態(tài)轉(zhuǎn)移方程(包括邊界條件)。
實際應(yīng)用中可以按以下幾個簡化的步驟進行設(shè)計:
?? ?(1)分析最優(yōu)解的性質(zhì),并刻畫其結(jié)構(gòu)特征。
?? ?(2)遞歸的定義最優(yōu)解。
?? ?(3)以自底向上或自頂向下的記憶化方式(備忘錄法)計算出最優(yōu)值
?? ?(4)根據(jù)計算最優(yōu)值時得到的信息,構(gòu)造問題的最優(yōu)解
五、算法實現(xiàn)的說明
??? 動態(tài)規(guī)劃的主要難點在于理論上的設(shè)計,也就是上面4個步驟的確定,一旦設(shè)計完成,實現(xiàn)部分就會非常簡單。
?? ? 使用動態(tài)規(guī)劃求解問題,最重要的就是確定動態(tài)規(guī)劃三要素:
(1)問題的階段
(2)每個階段的狀態(tài)
(3)從前一個階段轉(zhuǎn)化到后一個階段之間的遞推關(guān)系。
?? ? 遞推關(guān)系必須是從次小的問題開始到較大的問題之間的轉(zhuǎn)化,從這個角度來說,動態(tài)規(guī)劃往往可以用遞歸程序來實現(xiàn),不過因為遞推可以充分利用前面保存的子問題的解來減少重復(fù)計算,所以對于大規(guī)模問題來說,有遞歸不可比擬的優(yōu)勢,這也是動態(tài)規(guī)劃算法的核心之處。
?? ?確定了動態(tài)規(guī)劃的這三要素,整個求解過程就可以用一個最優(yōu)決策表來描述,最優(yōu)決策表是一個二維表,其中行表示決策的階段,列表示問題狀態(tài),表格需要填寫的數(shù)據(jù)一般對應(yīng)此問題的在某個階段某個狀態(tài)下的最優(yōu)值(如最短路徑,最長公共子序列,最大價值等),填表的過程就是根據(jù)遞推關(guān)系,從1行1列開始,以行或者列優(yōu)先的順序,依次填寫表格,最后根據(jù)整個表格的數(shù)據(jù)通過簡單的取舍或者運算求得問題的最優(yōu)解。
?? ? ? ? ?f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}
代碼樣例:
定義狀態(tài): dp[i][0] 表示第 i 天交易完后手里沒有股票的最大利潤, dp[i][1] 表示第 i 天交易完后手里持有一支股票的最大利潤(i 從 0 開始)class Solution {public int maxProfit(int[] prices, int fee) {int n = prices.length;int[][] dp = new int[n][2];dp[0][0] = 0;dp[0][1] = -prices[0];for (int i = 1; i < n; ++i) {dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);}return dp[n - 1][0];} }class Solution {public int maxProfit(int[] prices, int fee) {int n = prices.length;int sell = 0, buy = -prices[0];for (int i = 1; i < n; ++i) {sell = Math.max(sell, buy + prices[i] - fee);buy = Math.max(buy, sell - prices[i]);}return sell;} }分治算法
一、基本概念
?? 在計算機科學(xué)中,分治法是一種很重要的算法。字面上的解釋是“分而治之”,就是把一個復(fù)雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題……直到最后子問題可以簡單的直接求解,原問題的解即子問題的解的合并。這個技巧是很多高效算法的基礎(chǔ),如排序算法(快速排序,歸并排序),傅立葉變換(快速傅立葉變換)……
??? 任何一個可以用計算機求解的問題所需的計算時間都與其規(guī)模有關(guān)。問題的規(guī)模越小,越容易直接求解,解題所需的計算時間也越少。例如,對于n個元素的排序問題,當(dāng)n=1時,不需任何計算。n=2時,只要作一次比較即可排好序。n=3時只要作3次比較即可,…。而當(dāng)n較大時,問題就不那么容易處理了。要想直接解決一個規(guī)模較大的問題,有時是相當(dāng)困難的。
二、基本思想及策略
?? 分治法的設(shè)計思想是:將一個難以直接解決的大問題,分割成一些規(guī)模較小的相同問題,以便各個擊破,分而治之。
?? 分治策略是:對于一個規(guī)模為n的問題,若該問題可以容易地解決(比如說規(guī)模n較小)則直接解決,否則將其分解為k個規(guī)模較小的子問題,這些子問題互相獨立且與原問題形式相同,遞歸地解這些子問題,然后將各子問題的解合并得到原問題的解。這種算法設(shè)計策略叫做分治法。
?? 如果原問題可分割成k個子問題,1<k≤n,且這些子問題都可解并可利用這些子問題的解求出原問題的解,那么這種分治法就是可行的。由分治法產(chǎn)生的子問題往往是原問題的較小模式,這就為使用遞歸技術(shù)提供了方便。在這種情況下,反復(fù)應(yīng)用分治手段,可以使子問題與原問題類型一致而其規(guī)模卻不斷縮小,最終使子問題縮小到很容易直接求出其解。這自然導(dǎo)致遞歸過程的產(chǎn)生。分治與遞歸像一對孿生兄弟,經(jīng)常同時應(yīng)用在算法設(shè)計之中,并由此產(chǎn)生許多高效算法。
三、分治法適用的情況
?? ?分治法所能解決的問題一般具有以下幾個特征:
??? 1) 該問題的規(guī)模縮小到一定的程度就可以容易地解決
??? 2) 該問題可以分解為若干個規(guī)模較小的相同問題,即該問題具有最優(yōu)子結(jié)構(gòu)性質(zhì)。
??? 3) 利用該問題分解出的子問題的解可以合并為該問題的解;
??? 4) 該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子子問題。
第一條特征是絕大多數(shù)問題都可以滿足的,因為問題的計算復(fù)雜性一般是隨著問題規(guī)模的增加而增加;
第二條特征是應(yīng)用分治法的前提它也是大多數(shù)問題可以滿足的,此特征反映了遞歸思想的應(yīng)用;、
第三條特征是關(guān)鍵,能否利用分治法完全取決于問題是否具有第三條特征,如果具備了第一條和第二條特征,而不具備第三條特征,則可以考慮用貪心法或動態(tài)規(guī)劃法。
第四條特征涉及到分治法的效率,如果各子問題是不獨立的則分治法要做許多不必要的工作,重復(fù)地解公共的子問題,此時雖然可用分治法,但一般用動態(tài)規(guī)劃法較好。
四、分治法的基本步驟
分治法在每一層遞歸上都有三個步驟:
?? ?step1 分解:將原問題分解為若干個規(guī)模較小,相互獨立,與原問題形式相同的子問題;
?? ?step2 解決:若子問題規(guī)模較小而容易被解決則直接解,否則遞歸地解各個子問題
?? ?step3 合并:將各個子問題的解合并為原問題的解。
它的一般的算法設(shè)計模式如下:
??? Divide-and-Conquer(P)
??? 1. if |P|≤n0
??? 2. then return(ADHOC(P))
??? 3. 將P分解為較小的子問題 P1 ,P2 ,...,Pk
??? 4. for i←1 to k
??? 5. do yi ← Divide-and-Conquer(Pi) △ 遞歸解決Pi
??? 6. T ← MERGE(y1,y2,...,yk) △ 合并子問題
??? 7. return(T)
??? 其中|P|表示問題P的規(guī)模;n0為一閾值,表示當(dāng)問題P的規(guī)模不超過n0時,問題已容易直接解出,不必再繼續(xù)分解。ADHOC(P)是該分治法中的基本子算法,用于直接解小規(guī)模的問題P。因此,當(dāng)P的規(guī)模不超過n0時直接用算法ADHOC(P)求解。算法MERGE(y1,y2,...,yk)是該分治法中的合并子算法,用于將P的子問題P1 ,P2 ,...,Pk的相應(yīng)的解y1,y2,...,yk合并為P的解。
五、分治法的復(fù)雜性分析
??? 一個分治法將規(guī)模為n的問題分成k個規(guī)模為n/m的子問題去解。設(shè)分解閥值n0=1,且adhoc解規(guī)模為1的問題耗費1個單位時間。再設(shè)將原問題分解為k個子問題以及用merge將k個子問題的解合并為原問題的解需用f(n)個單位時間。用T(n)表示該分治法解規(guī)模為|P|=n的問題所需的計算時間,則有:
?T(n)= k T(n/m)+f(n)
??? 通過迭代法求得方程的解:
?? ?遞歸方程及其解只給出n等于m的方冪時T(n)的值,但是如果認為T(n)足夠平滑,那么由n等于m的方冪時T(n)的值可以估計T(n)的增長速度。通常假定T(n)是單調(diào)上升的,從而當(dāng)? mi≤n<mi+1時,T(mi)≤T(n)<T(mi+1)。?
六、可使用分治法求解的一些經(jīng)典問題
(1)二分搜索
(2)大整數(shù)乘法
?(3)Strassen矩陣乘法
(4)棋盤覆蓋
(5)合并排序
(6)快速排序
(7)線性時間選擇
(8)最接近點對問題
(9)循環(huán)賽日程表
(10)漢諾塔
七、依據(jù)分治法設(shè)計程序時的思維過程
?? ?實際上就是類似于數(shù)學(xué)歸納法,找到解決本問題的求解方程公式,然后根據(jù)方程公式設(shè)計遞歸程序。
1、一定是先找到最小問題規(guī)模時的求解方法
2、然后考慮隨著問題規(guī)模增大時的求解方法
3、找到求解的遞歸函數(shù)式后(各種規(guī)模或因子),設(shè)計遞歸程序即可。
貪心算法
一、基本概念: ? ?????所謂貪心算法是指,在對問題求解時,總是做出在當(dāng)前看來是最好的選擇。也就是說,不從整體最優(yōu)上加以考慮,他所做出的僅是在某種意義上的局部最優(yōu)解。 ?????貪心算法沒有固定的算法框架,算法設(shè)計的關(guān)鍵是貪心策略的選擇。必須注意的是,貪心算法不是對所有問題都能得到整體最優(yōu)解,選擇的貪心策略必須具備無后效性,即某個狀態(tài)以后的過程不會影響以前的狀態(tài),只與當(dāng)前狀態(tài)有關(guān)。 ????所以對所采用的貪心策略一定要仔細分析其是否滿足無后效性。 二、貪心算法的基本思路: ??? 1.建立數(shù)學(xué)模型來描述問題。 ??? 2.把求解的問題分成若干個子問題。 ??? 3.對每一子問題求解,得到子問題的局部最優(yōu)解。 ??? 4.把子問題的解局部最優(yōu)解合成原來解問題的一個解。 三、貪心算法適用的問題 ????? 貪心策略適用的前提是:局部最優(yōu)策略能導(dǎo)致產(chǎn)生全局最優(yōu)解。 ??? 實際上,貪心算法適用的情況很少。一般,對一個問題分析是否適用于貪心算法,可以先選擇該問題下的幾個實際數(shù)據(jù)進行分析,就可做出判斷。 ? 四、貪心算法的實現(xiàn)框架 ??? 從問題的某一初始解出發(fā); ??? while (能朝給定總目標(biāo)前進一步) ??? {? ????????? 利用可行的決策,求出可行解的一個解元素; ??? } ??? 由所有解元素組合成問題的一個可行解; ?? 五、貪心策略的選擇 ???? 因為用貪心算法只能通過解局部最優(yōu)解的策略來達到全局最優(yōu)解,因此,一定要注意判斷問題是否適合采用貪心算法策略,找到的解是否一定是問題的最優(yōu)解。 ? 六、例題分析 ??? 下面是一個可以試用貪心算法解的題目,貪心解的確不錯,可惜不是最優(yōu)解。 ??? [背包問題]有一個背包,背包容量是M=150。有7個物品,物品可以分割成任意大小。 ??? 要求盡可能讓裝入背包中的物品總價值最大,但不能超過總?cè)萘俊?/span> ??? 物品 A B C D E F G ??? 重量 35 30 60 50 40 10 25 ??? 價值 10 40 30 50 35 40 30 ??? 分析: ??? 目標(biāo)函數(shù): ∑pi最大 ??? 約束條件是裝入的物品總重量不超過背包容量:∑wi<=M( M=150) ??? (1)根據(jù)貪心的策略,每次挑選價值最大的物品裝入背包,得到的結(jié)果是否最優(yōu)? ??? (2)每次挑選所占重量最小的物品裝入是否能得到最優(yōu)解? ??? (3)每次選取單位重量價值最大的物品,成為解本題的策略。 ??? 值得注意的是,貪心算法并不是完全不可以使用,貪心策略一旦經(jīng)過證明成立后,它就是一種高效的算法。 ??? 貪心算法還是很常見的算法之一,這是由于它簡單易行,構(gòu)造貪心策略不是很困難。 ??? 可惜的是,它需要證明后才能真正運用到題目的算法中。 ??? 一般來說,貪心算法的證明圍繞著:整個問題的最優(yōu)解一定由在貪心策略中存在的子問題的最優(yōu)解得來的。 ??? 對于例題中的3種貪心策略,都是無法成立(無法被證明)的,解釋如下: ??? (1)貪心策略:選取價值最大者。反例: ??? W=30 ??? 物品:A B C ??? 重量:28 12 12 ??? 價值:30 20 20 ??? 根據(jù)策略,首先選取物品A,接下來就無法再選取了,可是,選取B、C則更好。 ??? (2)貪心策略:選取重量最小。它的反例與第一種策略的反例差不多。 ??? (3)貪心策略:選取單位重量價值最大的物品。反例: ??? W=30 ??? 物品:A B C ??? 重量:28 20 10 ??? 價值:28 20 10 ??? 根據(jù)策略,三種物品單位重量價值一樣,程序無法依據(jù)現(xiàn)有策略作出判斷,如果選擇A,則答案錯誤。 利率最大貪心算法: class Solution {public int maxProfit(int[] prices, int fee) {int n = prices.length;int buy = prices[0] + fee;int profit = 0;for (int i = 1; i < n; ++i) {if (prices[i] + fee < buy) {buy = prices[i] + fee;} else if (prices[i] > buy) {profit += prices[i] - buy;buy = prices[i];}}return profit;} }回溯法
1、概念
????? 回溯算法實際上一個類似枚舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當(dāng)發(fā)現(xiàn)已不滿足求解條件時,就“回溯”返回,嘗試別的路徑。
?? 回溯法是一種選優(yōu)搜索法,按選優(yōu)條件向前搜索,以達到目標(biāo)。但當(dāng)探索到某一步時,發(fā)現(xiàn)原先選擇并不優(yōu)或達不到目標(biāo),就退回一步重新選擇,這種走不通就退回再走的技術(shù)為回溯法,而滿足回溯條件的某個狀態(tài)的點稱為“回溯點”。
???? 許多復(fù)雜的,規(guī)模較大的問題都可以使用回溯法,有“通用解題方法”的美稱。
2、基本思想
???在包含問題的所有解的解空間樹中,按照深度優(yōu)先搜索的策略,從根結(jié)點出發(fā)深度探索解空間樹。當(dāng)探索到某一結(jié)點時,要先判斷該結(jié)點是否包含問題的解,如果包含,就從該結(jié)點出發(fā)繼續(xù)探索下去,如果該結(jié)點不包含問題的解,則逐層向其祖先結(jié)點回溯。(其實回溯法就是對隱式圖的深度優(yōu)先搜索算法)。
?????? 若用回溯法求問題的所有解時,要回溯到根,且根結(jié)點的所有可行的子樹都要已被搜索遍才結(jié)束。
?????? 而若使用回溯法求任一個解時,只要搜索到問題的一個解就可以結(jié)束。
3、用回溯法解題的一般步驟:
??? (1)針對所給問題,確定問題的解空間:
??????????? 首先應(yīng)明確定義問題的解空間,問題的解空間應(yīng)至少包含問題的一個(最優(yōu))解。
??? (2)確定結(jié)點的擴展搜索規(guī)則
??? (3)以深度優(yōu)先方式搜索解空間,并在搜索過程中用剪枝函數(shù)避免無效搜索。
4、算法框架
???? (1)問題框架
????? 設(shè)問題的解是一個n維向量(a1,a2,………,an),約束條件是ai(i=1,2,3,…..,n)之間滿足某種條件,記為f(ai)。
???? (2)非遞歸回溯框架
1: int a[n],i;2: 初始化數(shù)組a[];3: i = 1;4: while (i>0(有路可走) and (未達到目標(biāo))) // 還未回溯到頭5: {6: if(i > n) // 搜索到葉結(jié)點7: { 8: 搜索到一個解,輸出;9: }10: else // 處理第i個元素11: { 12: a[i]第一個可能的值;13: while(a[i]在不滿足約束條件且在搜索空間內(nèi))14: {15: a[i]下一個可能的值;16: }17: if(a[i]在搜索空間內(nèi))18: {19: 標(biāo)識占用的資源;20: i = i+1; // 擴展下一個結(jié)點21: }22: else 23: {24: 清理所占的狀態(tài)空間; // 回溯25: i = i –1; 26: }27: }(3)遞歸的算法框架
???????? 回溯法是對解空間的深度優(yōu)先搜索,在一般情況下使用遞歸函數(shù)來實現(xiàn)回溯法比較簡單,其中i為搜索的深度,框架如下:
1: int a[n];2: try(int i)3: {4: if(i>n)5: 輸出結(jié)果;6: else7: {8: for(j = 下界; j <= 上界; j=j+1) // 枚舉i所有可能的路徑9: {10: if(fun(j)) // 滿足限界函數(shù)和約束條件11: {12: a[i] = j;13: ... // 其他操作14: try(i+1);15: 回溯前的清理工作(如a[i]置空值等);16: }17: }18: }19: }分支限界法
一、基本描述
??? 類似于回溯法,也是一種在問題的解空間樹T上搜索問題解的算法。但在一般情況下,分支限界法與回溯法的求解目標(biāo)不同。回溯法的求解目標(biāo)是找出T中滿足約束條件的所有解,而分支限界法的求解目標(biāo)則是找出滿足約束條件的一個解,或是在滿足約束條件的解中找出使某一目標(biāo)函數(shù)值達到極大或極小的解,即在某種意義下的最優(yōu)解。
?? (1)分支搜索算法
??? 所謂“分支”就是采用廣度優(yōu)先的策略,依次搜索E-結(jié)點的所有分支,也就是所有相鄰結(jié)點,拋棄不滿足約束條件的結(jié)點,其余結(jié)點加入活結(jié)點表。然后從表中選擇一個結(jié)點作為下一個E-結(jié)點,繼續(xù)搜索。
???? 選擇下一個E-結(jié)點的方式不同,則會有幾種不同的分支搜索方式。
?? 1)FIFO搜索
?? 2)LIFO搜索
?? 3)優(yōu)先隊列式搜索
(2)分支限界搜索算法?
二、分支限界法的一般過程
??? 由于求解目標(biāo)不同,導(dǎo)致分支限界法與回溯法在解空間樹T上的搜索方式也不相同。回溯法以深度優(yōu)先的方式搜索解空間樹T,而分支限界法則以廣度優(yōu)先或以最小耗費優(yōu)先的方式搜索解空間樹T。
??? 分支限界法的搜索策略是:在擴展結(jié)點處,先生成其所有的兒子結(jié)點(分支),然后再從當(dāng)前的活結(jié)點表中選擇下一個擴展對點。為了有效地選擇下一擴展結(jié)點,以加速搜索的進程,在每一活結(jié)點處,計算一個函數(shù)值(限界),并根據(jù)這些已計算出的函數(shù)值,從當(dāng)前活結(jié)點表中選擇一個最有利的結(jié)點作為擴展結(jié)點,使搜索朝著解空間樹上有最優(yōu)解的分支推進,以便盡快地找出一個最優(yōu)解。
??? 分支限界法常以廣度優(yōu)先或以最小耗費(最大效益)優(yōu)先的方式搜索問題的解空間樹。問題的解空間樹是表示問題解空間的一棵有序樹,常見的有子集樹和排列樹。在搜索問題的解空間樹時,分支限界法與回溯法對當(dāng)前擴展結(jié)點所使用的擴展方式不同。在分支限界法中,每一個活結(jié)點只有一次機會成為擴展結(jié)點。活結(jié)點一旦成為擴展結(jié)點,就一次性產(chǎn)生其所有兒子結(jié)點。在這些兒子結(jié)點中,那些導(dǎo)致不可行解或?qū)е路亲顑?yōu)解的兒子結(jié)點被舍棄,其余兒子結(jié)點被子加入活結(jié)點表中。此后,從活結(jié)點表中取下一結(jié)點成為當(dāng)前擴展結(jié)點,并重復(fù)上述結(jié)點擴展過程。這個過程一直持續(xù)到找到所求的解或活結(jié)點表為空時為止。
三、回溯法和分支限界法的一些區(qū)別
??? 有一些問題其實無論用回溯法還是分支限界法都可以得到很好的解決,但是另外一些則不然。也許我們需要具體一些的分析——到底何時使用分支限界而何時使用回溯呢?
回溯法和分支限界法的一些區(qū)別:
?? 方法對解空間樹的搜索方式???????存儲結(jié)點的常用數(shù)據(jù)結(jié)構(gòu)????? 結(jié)點存儲特性常用應(yīng)用
? 回溯法深度優(yōu)先搜索堆棧活結(jié)點的所有可行子結(jié)點被遍歷后才被從棧中彈出找出滿足約束條件的所有解
? 分支限界法廣度優(yōu)先或最小消耗優(yōu)先搜索隊列、優(yōu)先隊列每個結(jié)點只有一次成為活結(jié)點的機會找出滿足約束條件的一個解或特定意義下的最優(yōu)解
參考:
經(jīng)典中的經(jīng)典算法:動態(tài)規(guī)劃(詳細解釋,從入門到實踐,逐步講解)
五大常用算法之二:動態(tài)規(guī)劃算法
總結(jié)
- 上一篇: 关于WAMP安装后出现403的解决方法
- 下一篇: angular7中使用iframe来加载