1. 程式人生 > 其它 >演算法第五章《回溯法》上機實踐報告

演算法第五章《回溯法》上機實踐報告

一.實踐題目名稱

最小重量機器設計問題

二.問題描述

設某一機器由n個部件組成,每一種部件都可以從m個不同的供應商處購得。設wij​是從供應商j 處購得的部件i的重量,cij​是相應的價格。試設計一個演算法,給出總價格不超過d的最小重量機器設計。

輸入格式:

第一行有3 個正整數n ,m和d, 0<n<30, 0<m<30, 接下來的2n 行,每行n個數。前n行是c,後n行是w。

輸出格式:

輸出計算出的最小重量,以及每個部件的供應商

三.演算法描述

1.請用回溯法的方法分析最小重量機器設計問題

遍歷順序:從一個節點開始,以深度優先的方法搜尋解空間,每一個葉子結點都代表著一個可能性,輸出

“重量”最小的葉子結點,並用剪枝函式避免無效的搜尋。

剪枝方式

1)約束以:當前價格+該零件價格<總價格d”作為判斷條件刪除不滿足約束的子樹。

2)限以:當前重量+該零件重量<最小重量紀錄”作為判斷條件將一定不為最優解的子樹刪除

1.1說明“最小重量機器設計問題"的解空間

本題的解空間為長度為n的供應商各種組合向量,總價格不超過d的每個部件的供應商選擇的集合所有可能的部件重量值,{(1,3,1),(1,3,2),(1,3,3)}

1.2說明最小重量機器設計問題"的解空間樹

解空間為一棵m叉樹,共有n層,每一層分別表示需要一個零件每一個節點的m個分支表示對於每個零件

m個供應商可選擇

1.3在遍歷解空間樹的過程中,每個結點的狀態值是什麼

間為一該路徑上從第一個節點到該節點的當前總價值cv,和當前總重量cw。

#include<iostream>
using namespace std;
 
int n,m,d;
int c[999][999],w[999][999];

int cw=0,cp=0;//記錄該分支最小的重量和價值
int minw=999; 
int x[999];//儲存當前重量下每個部件供應商的號碼
int minx[999];

void backtrack(int i) 
{
    //遍歷到了子葉 
    if(i>n) 
    {
        
if(cp<=d&&cw<minw) { minw=cw; for(int j=1; j<=n; j++) { minx[j]=x[j]; } } } else { for(int j=1; j<=m; j++) { x[i]=j;//記錄下當前部件是哪一個供應商 cw=cw+w[i][j]; cp=cp+c[i][j]; if(cp<=d&&cw<minw) { backtrack(i+1); } //回溯 cw=cw-w[i][j]; cp=cp-c[i][j]; } } } int main() { //n個元件 m個供應商 總價格不超過d cin>>n>>m>>d; //第i個零件在第j個產家的價錢 for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) cin>>c[i][j]; //第i個零件在第j個產家的重量 for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) cin>>w[i][j]; //從第一個零件開始遍歷 backtrack(1); //輸出 cout<<minw<<endl; for(int i=1; i<=n; i++) cout<<minx[i]<<" "; return 0; }

四.對回溯法的理解

回溯法是一個採用深度優先的策略,從根節點開始進行深度遍歷,先判斷該節點是否包含問題的解。如果不包含,則跳過對以該節點為根的子樹的搜尋,回溯到其它祖先節點,直到所有子樹都被遍歷完成,但如果不進行有效的剪枝的話,解空間是非常龐大的,所以我們在平時一定要用約束法和限界法進行有效的剪枝,以節省時間和空間上的開銷。