回溯 皇后 演算法筆記 演算法筆記

2021-10-16 16:20:08 字數 3676 閱讀 9227

遞迴演算法

能夠用遞迴解決的問題需要滿足三個條件:原問題可以轉換為乙個或多個子問題來求解,而這些子問題的求解方法和原問題完全相同,只是規模不同;

遞迴呼叫次數必須是有限的;

必須有結束遞迴的條件(遞迴出口)來終止遞迴。

設計遞迴演算法模式先求解問題的遞迴模型。

在設計遞迴演算法的時候,如果糾結遞迴樹的每乙個階段的話,就會極為複雜。因此,只考慮遞迴樹中的第一層和第二層之間的關係即可,即「大問題」 和 「小問題」 的關係,其他關係類似。

求解問題的遞迴模型:對原問題 f(n) 進行分析,假設出合理的小問題 f(n-1);

假設小問題 f(n-1) 是可解的,在此基礎上確定大問題 f(n) 的解,即給出 f(n) 與 f(n-1) 之間的關係,也就是確定了遞迴體。(與數學歸納法中確定 i=n-1 時成立,再求證 i=n 時等式成立的過程相似)。還要明確需要返回什麼資訊給上一層遞迴呼叫。

確定乙個特定情況(如 f(0) 或 f(1))的解,由此作為遞迴出口。(與數學歸納法中求證 i=0 或 i=1時等式成立相似)

例子:求陣列中最小值:1

18* 遞迴求陣列最大值

* @param arr 目標陣列

* @param i 起始下標

* @return

private static int (int arr, int i) else 中逆序對有 <3,1> <3,2>1

40static int getreversecount(int arr, int low, int high) else 大整數乘法

動態規劃動態規劃過程是:每次決策依賴於當前狀態,又隨即引起狀態的轉移。是一種分階段求解決策問題的數學思想。總結起來就是一句話,大事化小,小事化了。

基本思想與分治法類似,也是將待求解的問題分解為若干個子問題(階段),按順序求解子階段,前一子問題的解,為後一子問題的求解提供了有用的資訊。在求解任一子問題時,列出各種可能的區域性解,通過決策保留那些有可能達到最優的區域性解,丟棄其他區域性解。依次解決各子問題,最後乙個子問題就是初始問題的解。

通用遞推式:

f(n,m)=max

優化:由於動態規劃解決的問題多數有重疊子問題這個特點,為減少重複計算,對每乙個子問題只解一次,將其不同階段的不同狀態儲存在乙個二維陣列中。

分治法最大的差別:

適用的情況

能採用動態規劃求解的問題的一般要具有3個性質:最優化原理:如果問題的最優解所包含的子問題的解也是最優的,就稱該問題具有最優子結構,即滿足最優化原理。

無後效性:即某階段狀態一旦確定,就不受這個狀態以後決策的影響。也就是說,某狀態以後的過程不會影響以前的狀態,只與當前狀態有關。

求解的基本步驟

​ 初始狀態→│決策1│→│決策2│→…→│決策n│→結束狀態劃分階段:按照問題的時間或空間特徵,把問題分為若干個階段。在劃分階段時,注意劃分後的階段一定要是有序的或者是可排序的,否則問題就無法求解。

確定狀態和狀態變數->(遞迴的定義最優解。):將問題發展到各個階段時所處於的各種客觀情況用不同的狀態表示出來。當然,狀態的選擇要滿足無後效性。

確定決策並寫出狀態轉移方程:因為決策和狀態轉移有著天然的聯絡,狀態轉移就是根據上一階段的狀態和決策來匯出本階段的狀態。所以如果確定了決策,狀態轉移方程也就可寫出。但事實上常常是反過來做,根據相鄰兩個階段的狀態之間的關係來確定決策方法和狀態轉移方程。

尋找邊界條件:給出的狀態轉移方程是乙個遞推式,需要乙個遞推的終止條件或邊界條件。

動態規劃案例

0, 1揹包問題

兩種情況來分析, 要拿的東西能不能裝進揹包,能裝進去的話,要不要那它(看價值)如果第k件物品的重量w[k]比此時的揹包的剩餘重量c大了,那我肯定是拿不動了,即w[k]>c。所以此時包中物品的價值就是我拿的前乙個物品之後包中的價值,即 b(k,c)=b(k-1,c).包中剩餘空間不變,還是c。

那麼第二種情況,如果我拿得動第k件物品,即第k件物品的重量w[k]

拿走k號物品,那麼此時包中物品的總價值b(k,c)=b(k-1,c-w[k])+v[k]拿了第k件物品後,那我的包中的價值肯定就是原先的價值再加上第k件物品的價值,而且拿了之後包中的剩餘容量就為c-w[k]了。 總結一下,就是如下的公式了:b(k,c)=max

120class main;

int v = ;

int n = 6, w = 21;

int b = new int[n][w];

for (int k = 1; k < n; k++) else 1

26//遞迴方式

* @param w 重量陣列

* @param v 物品價值陣列

* @param capacity 揹包容量

* @param i 物品i開始

* @return

private static int getvalue(int w, int v, int capacity, int i) else else 01揹包問題

用回溯法解問題時,應明確定義問題的解空間。問題的解空間至少包含問題的乙個(最優)解。對於 n=3 時的 0/1 揹包問題,可用一棵完全二叉樹表示解空間

求解步驟

1)針對所給問題,定義問題的解空間;

2)確定易於搜尋的解空間結構;

3)以深度優先方式搜尋解空間,並在搜尋過程中用剪枝函式避免無效搜尋。

常用的剪枝函式:用約束函式在擴充套件結點處剪去不滿足約束的子樹;用限界函式剪去得不到最優解的子樹。

回溯法對解空間做深度優先搜尋時,有遞迴回溯和迭代回溯(非遞迴)兩種方法,但一般情況下用遞迴方法實現回溯法。

演算法描述

解 0/1 揹包問題的回溯法在搜尋解空間樹時,只要其左兒子結點是乙個可行結點,搜尋就進入其左子樹。當右子樹中有可能包含最優解時才進入右子樹搜尋。否則將右子樹剪去。1

25void dfs(int i,int cv,int cw)

主函式部分1

27int main()

int i;

bestval=0;

cout<

cin>>totcap;

cout<

cin>>n;

cout<

for(i=1;i<=n;i++)

cin>>w[i];

cout<

for(i=1;i<=n;i++)

cin>>val[i];

dfs(1,0,0);

cout<

cout<

cout<

for(i=1;i<=n;i++)

if(bestx[i]==1)

cout<

cout<

return 0;

分支限界法類似於回溯法,也是一種在問題的解空間樹t上搜尋問題解的演算法。但在一般情況下,分支限界法與回溯法的求解目標不同。回溯法的求解目標是找出t中滿足約束條件的所有解,而分支限界法的求解目標則是找出滿足約束條件的乙個解,或是在滿足約束條件的解中找出使某一目標函式值達到極大或極小的解,即在某種意義下的最優解。

​ 選擇下乙個e-結點的方式不同,則會有幾種不同的分支搜尋方式。

1)fifo搜尋

2)lifo搜尋

3)優先佇列式搜尋

回溯法和分支限界法的一些區別方法對解空間樹的搜尋方式

儲存結點的常用資料結構

結點儲存特性常用應用

回溯法深度優先搜尋堆疊活結點的所有可行子結點被遍歷後才被從棧中彈出找出滿足約束條件的所有解

分支限界法廣度優先或最小消耗優先搜尋佇列、優先佇列每個結點只有一次成為活結點的機會找出滿足約束條件的乙個解或特定意義下的最優解

回溯 皇后 演算法筆記 演算法筆記

分治演算法 線性時間選擇 o n 33 隨機線性選擇 偽 o n int partition type a,int p,int r return table n 1 w 1 main function else else lowcost i 0 for int i 1 i n i int temp ...

回溯 皇后 演算法筆記 演算法筆記 回溯法

1 0 1揹包問題 思路 構造乙個二叉樹,每個商品都有兩種狀態,要或者不要。如果要就在這個節點的左枝掛子節點,如果不要就在右節點掛子節點。如果全部商品都分配完狀態之後就回溯,回溯到乙個還有其他選擇的節點,接著往這個選擇發展節點,然後再回溯,然後再往下。直到無路可走,就結束了。假如限制重量是10,總共...

回溯 皇后 演算法筆記 回溯演算法 N皇后問題

n 皇后問題研究的是如何將 n 個皇后放置在 n n 的棋盤上,並且使皇后彼此之間不能相互攻擊。上圖為 8 皇后問題的一種解法。給定乙個整數 n,返回所有不同的 n 皇后問題的解決方案。每一種解法包含乙個明確的 n 皇后問題的棋子放置方案,該方案中 q 和 分別代表了皇后和空位。示例 輸入 4 輸出...