深度優先搜尋解決簡單揹包問題(遞迴)

2021-09-25 12:34:53 字數 1663 閱讀 3276

hh還是《演算法筆記》中的專題,在271頁。

問題:有n件物品已知每件的重量w[i],價值c[i],現在需要選出若干物品放入乙個容積為v的揹包中,使得選入揹包的物品重量和不超過v的前提下,讓揹包中的物品價值和最大,求最大價值(1<=n<=20)。

這裡採用的思想是深度優先搜尋,實現方法是遞迴法。

遞迴式是對每個物品都有選和不選兩種操作(岔路口);

選擇,則當前總重量和總價值都加上當前物品的重量的價值,否則不加。

遞迴邊界就是處理完全部的物品(死胡同)。

在所有可能的方案都列舉之後,再選出符合兩個條件的情況:

1.選中的物品重量和不超過v;2.揹包中物品價值最大。

輸入:n件物品 v容積

n件物品的重量

n件物品的價值

輸出:最大價值(最優值)

(這裡我加了一點,可以輸出最優解(每個被選中物品的價值))

(記錄最優解的方法見《演算法筆記》273頁,利用stl容器vector(變長陣列)(見191頁)temp存放臨時方案,ans存放當前最好方案)

**如下:

// 深度優先搜尋解決揹包問題

#include

#include

using namespace std;

vector temp,ans;

int w[30]

;int c[30]

;int n,v=

0;int maxnum=0;

void

dfs(int index,int numw,int numc)

return;}

//選index號數

temp.

push_back

(c[index]);

//把當前物品價值加入temp中

dfs(index+

1,numw+w[index]

,numc+c[index]);

temp.

pop_back()

;//分支結束後把c[index]從temp中除去,使它不影響「不選index」這條分支

//不選index號數

dfs(index+

1,numw,numc);}

int main()

for(int i=

0;i)dfs(0

,0,0

);printf

("%d\n"

,maxnum)

;for

(int i=

0;isize()

;i++

)return0;

}

輸入資料:

5 83 5 1 2 2

4 5 2 1 3

輸出結果:

104 2 1 3

經檢驗,結果正確。

不足:很明顯這個題的最佳方案不止一種,4 2 1 3和 5 2 3都符合要求,但只輸出了乙個,所以我認為這種利用vector的方法適用於最優解僅乙個的題目。

目前我也沒有掌握輸出所有最優解的方法,我只是把273頁的方法和揹包結合到了一起。書上確實有一句話「資料保證這樣的方案唯一」。

當然,如果僅僅輸出乙個最優值,那麼剪枝法更值得一試。

進入岔路2「選第index件物品」的條件是:加入第index件物品之後未超過容量v(272頁,感興趣的可以照書敲敲試試)。

感謝閱讀。

深度優先搜尋解決全排列問題

題目 假如有編號為1 2 3的3張撲克牌和編號為1 2 3的3個盒子。現在需要將這3張撲克牌分別放到3個盒子裡,並且每個盒子有且只能放一張撲克牌。那麼一共有多少種不同的排法?及注釋 include 全域性變數,陣列元素值自動初始化為0 int a 10 充當盒子編號 int book 10 用boo...

深度優先搜尋解決八皇后問題

八皇后問題是什麼 八皇后問題,是乙個古老而著名的問題,是回溯演算法的典型案例。該問題是國際西洋棋棋手馬克斯 貝瑟爾於1848年提出 在8 8格的西洋棋上擺放八個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。高斯認為有76種方案。1854年在柏林的象棋雜誌...

記憶化搜尋解決揹包問題

為什麼要用二維陣列進行紀錄?記憶化最麻煩的還是記憶值的準確性 include include using namespace std struct noded 10000 long long n,m long long dp 1000 1000 一開始我直接使用的dp 1000000 以為將每個m對...