例如,對於 n=3 的 01-揹包問題,可以用完全二叉樹表示其解空間:
解空間樹的型別
子集樹:當所給問題是從 n 個元素的集合 s 中找出 s 滿足某種性質的子集時,相應的解空間樹稱為子集樹。
void
backtrack
(int t)
}}
排列樹:當所給問題是確定 n 個元素滿足某種性質的排列時,相應的解空間被稱為排列樹。
void
backtrack
(int t)
}}
回溯的過程:回溯法從根節點出發,以深度優先方式搜尋整個解空間。
這個開始節點成為活結點,也成為當前的擴充套件結點。在當前擴充套件結點處,搜尋向縱深方向移至乙個新結點,則這個新結點成為新的活結點,並成為當前的擴充套件結點。
如果當前擴充套件結點不能再移動,則當前擴充套件結點成為死結點,此時應該回溯到最近的活結點處。
直到在解空間中已無活結點則搜尋結束。
解題的步驟:
針對所給問題,定義問題的解空間
確定易於搜尋的解空間結構
以深度優先方式搜尋解空間,並在搜尋過程中用剪枝函式避免無效搜尋
問題:給定 n 個作業的集合 j=,每個作業 ji都有兩項任務分別在兩台機器上完成,每個作業必須先有機器1處理,然後由機器2處理。fji 是作業 i 在機器 j 上完成處理的時間。所有作業在機器2上完成處理的時間和稱為該作業排程的完成時間和,批處理作業排程即給出最優排程使得完成時間和最小。
解題思路:
可以確定解空間是一顆排列樹,設 x=[1,2,…,n] 是所給的 n 個作業,則相應的排列樹由 x[1:n] 的所有排列構成。
**:
public
class
flowshop
bestf = f;
}else}}
}}
問題:由14個「+」號和14個「-」號組成的符號三角形。2個同號下面是「+」號,2個異號下面是「-」號。
在一般情況下,符號三角形第一行有n個符號,該問題要求對於給定n計算有多少種不同的符號三角形。使其所含的+ — 個數相同。
解題思路:
用 x[1:n] 表示符號三角形的第一行的 n 個字元
**:
public
class
********s
}backtrack(1
);return sum;
}private
static
void
backtrack
(int t)
backtrack
(t+1);
for(
int j=
2;j<=t;j++
) count -= i;}}
}}
問題:在n×n格的西洋棋上擺放n個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。
解題思路:
用 x[1:n] 表示 n 後問題的解,x[i] 表示皇后 i 放在棋盤的第 i 行的第 j 列。不同列,則 x[i] 都不相同。斜線上不能相同即,對於兩個皇后(i,j) 和 (k,l),|i-k| =/= |j-l|。
**:
public
class
nqueen
backtrack(1
);return sum;
}private
static
boolean
place
(int k)
return
true;}
private
void
backtrack
(int t)}}
}
在動態規劃中有問題描述以及動態規劃的解題方法,這裡只討論回溯法的解法。
解題思路:
可用子集樹來表示解空間,在搜尋空間樹時,只要其左兒子結點是乙個可行點就進入,而右兒子只有在可能包含最優解時才進入,否則剪枝。
偽**:
static
double c;
//揹包容量
static
int n;
//物品數
static
double
w;//重量
static
double
p;//價值
static
double cw;
//當前重量
static
double cp;
//當前價值
static
double bestp;
//最優價值
private
static
void
backtrack
(int i)
if(cw + w[i]
<= c)if(
bound
(i+1
)>bestp)
//判斷右子樹的價值有沒可能超過左子樹
backtrack
(i+1);
//超過則進入右子樹
}
問題:售貨員要到n個城市去推銷商品,已知各城市之間的路程(代價)a,試選擇一條路,從第乙個城市出發經過每個城市一遍,最後回到出發城市所耗費的代價最小。
解題思路:
分析可知解空間是一棵排列樹,每一條從根節點到達葉子結點的路徑代表了n個頂點的一種排列。定義x[n]記錄可行解。
剪枝函式:兩個城市之間是否連通,到達當前為止的代價是否已經超過了最優代價,當前城市是否已經走過。
貪心演算法經典例子
貪心演算法總是作出在當前看來最好的選擇。也就是說貪心演算法並不從整體最優考慮,它所作出的選擇只是在某種意義上的區域性最優選擇。基本思想 貪心演算法並不從整體最優上加以考慮,它所做的選擇只是在某種意義上的區域性最優解。基本要素 最優子結構性質和貪心選擇性質。和動態規劃區別 動態規劃演算法中,每步所做的...
回溯演算法python 數獨問題 回溯演算法經典例題
之前我們已經簡單地說明了怎樣用回溯演算法解決數獨的問題,思路如下 從第乙個空格開始。依次嘗試 1 到 9 的數字,如果數字與盤面衝突就換成下乙個數字,如果不衝突就去往第二個空格 在第二個空格,同樣依次嘗試 1 到 9 的數字,如果與盤面衝突就換成下乙個數字,如果不衝突就去往第三個空格,以此類推 當最...
演算法 經典演算法
1 匹配演算法 匹配開始,從長的字串開始,匹配成功,長的和短的字串均向後匹配,而匹配失敗,則長的字串從開始的位置向後乙個字元,重新開始匹配,而短的字串則完全從頭開始。匹配演算法 param str1 長匹配字串 param str2 短的匹配字串 return 匹配成功 返回短字串在長字串開始的位置...