演算法第5章實驗報告
演算法第5章實驗報告
1.請用回溯法的方法分析“最小重量機器設計問題”
演算法描述:
由於題目已經給出總價格的上限,因此演算法通過使用回溯來選擇合適的機器使得在總價格不超過 d 時得到的機器重量最小。首先初始化當前價格 cc=0 ,當前重量 cw=0 ,此外,還要設定一個變數 mincw 表示選擇機器的總重量,初始化其為每個部件從1號供應商購買的重量。在迴圈選擇 i 號機器時,判斷從 j 號供應商購買機器後的價格是否大於總價格,如果不大於則選擇,否則不選,繼續選擇下一供應商進行判斷。在得到一個合適的供應商後,繼續選擇下一機器的供應商,從第一個選到最後一個供應商,記錄下每個部件選擇的供應商 x[i] 。當所有機器選擇結束後,判斷得到的總重量是否比之前的 mincw 小,如果小就賦給 mincw ,然後從這一步開始,回溯到上一機器,選擇下一合適供應商,繼續搜尋可行解,直到將整個排列樹搜尋完畢。這樣,最終得到的 mincw 即為最優解。
當然,考慮到演算法的時間複雜度,還可以加上一個剪枝條件,即在每次選擇某一機器時,再判斷選擇後的當前重量是否已經大於之前的 mincw ,如果大於就沒必要繼續搜尋了,因為得到的肯定不是最優解。
解題步驟:
a.部件有 n 個,供應商有 m 個,分別用兩個二維陣列 w[i][j] 和 c[i][j] 儲存從供應商 j 處購得的部件 i 的重量和相應價格,d 為總價格的上限。
b.用遞迴函式 backtrack(t) 來實現回溯法搜尋排列樹(形式引數 t 表示遞迴深度)。
① 若 cc > d ,則為不可行解,剪去相應子樹,返回到 t-1 層繼續執行。
② 若 cw >= mincw ,則不是最優解,剪去相應子樹,返回到 t-1 層繼續執行。
③ 若 t > n ,則演算法搜尋到一個葉結點,用 x[i] 對每個部件的供應商進行記錄,用 mincw 對最優解進行記錄,返回到 t-1 層繼續執行;
④ 用 for 迴圈對 n 個順序部件從 m 個不同的供應商購得的情況進行選擇(1 ≤ i ≤ m)。
c.主函式呼叫一次 backtrack(1) 即可完成整個回溯搜尋過程,最終得到的mincw即為所求最小總重量,x[i] 即為每個部件選擇的供應商。
程式碼描述:
1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 5 int n,m,d; 6 int c[30][30]; 7 int w[30][30]; 8 int x[30]; 9 int cc; 10 int cw; 11 int mincw = 10000; 12 int minx[30]; 13 14 void backtrack(int t){ 15 if (t > n){ 16 if(cw < mincw){ 17 mincw = cw;18 for (int i = 1; i < t; i++){ 19 minx[i] = x[i]; 20 } 21 } 22 return; 23 }else{ 24 for (int i = 1; i <= m; i++){ 25 x[t] = i; 26 cc = cc + c[t][i]; 27 cw = cw + w[t][i]; 28 if (cc <= d && cw < mincw){ 29 backtrack(t+1); 30 } 31 cc = cc - c[t][i]; 32 cw = cw - w[t][i]; 33 } 34 35 } 36 37 } 38 39 int main(int argc, char** argv) { 40 cin >> n >> m >> d; 41 for (int i = 1; i <= n; i++){ 42 for (int j = 1; j <= m; j++){ 43 cin >> c[i][j]; 44 } 45 } 46 for (int i = 1; i <= n; i++){ 47 for (int j = 1; j <= m; j++){ 48 cin >> w[i][j]; 49 } 50 } 51 backtrack(1); 52 cout << mincw << endl; 53 for (int i = 1; i <= n; i++){ 54 cout << minx[i] << " "; 55 } 56 return 0; 57 }
1.1說明“最小重量機器設計問題"的解空間
解空間即進行窮舉的搜尋空間,包含所有的可能解,這裡以樣例為例寫出解空間:
(i,j,k)表示第1個部件選擇第i個供應商,第2個部件選擇第j個供應商,第3個部件選擇第k個供應商,以此類推。
(1,1,1)(1,1,2)(1,1,3)
(1,2,1)(1,2,2)(1,2,3)
(1,3,1)(1,3,2)(1,3,3)
(2,1,1)(2,1,2)(2,1,3)
(2,2,1)(2,2,2)(2,2,3)
(2,3,1)(2,3,2)(2,3,3)
(3,1,1)(3,1,2)(3,1,3)
(3,2,1)(3,2,2)(3,2,3)
(3,3,1)(3,3,2)(3,3,3)
1.2說明“最小重量機器設計問題"的解空間樹
1.3在遍歷解空間樹的過程中,每個結點的狀態值是什麼。
每個結點的狀態值是該點當前的總重量 cw 和總價格 cc 。
2.你對回溯演算法的理解
2.1 基本概念:
回溯法思路的簡單描述是:把問題的解空間轉化成了圖或者樹的結構表示,然後使用深度優先搜尋策略進行遍歷,遍歷的過程中記錄和尋找所有可行解或者最優解。
2.2 使用條件:
當問題是要求滿足某種性質(約束條件)的所有解或最優解時,便可以使用回溯法,其實有暴力剪枝的意味
2.3 使用思想:
回溯法常常使用DFS(深度優先搜尋)來進行對解空間的答案搜尋。
首先從根根部節點出發搜尋解空間,當搜尋至解空間的某一節點時,先利用約束或限界剪枝函式來判斷該節點是否是問題的解。如果不是,則跳過對該節點為根的子樹的搜尋,逐層向其祖先節點回溯;否則,進入該子樹,繼續按深度優先策略搜尋。
回溯法的基本行為是暴力搜尋,搜尋過程進行剪枝來為了避免無效冗餘的搜尋。
剪枝主要包括兩類:
1. 使用約束函式,剪去不滿足約束條件的路徑;
2. 使用限界函式,剪去不能得到最優解的路徑。
2.4 回溯演算法的經典問題種類:
(1)裝載問題
(2)0-1揹包問題
(3)旅行售貨員問題
(4)n後問題