在前面文章我們使用動態規劃求解了揹包問題,時間複雜度是o(
cn) ,當我們的c的值非常大的時候,說消耗的時間也是非常大的!
接下來我們就使用回溯法來求解這個問題,其時間複雜度為o(
n2n)
,這個結果當我們的c的值是小於2n
的時候,該演算法所需的時間是小於動態規劃的!
既然使用了回溯法,我們就的構造解析樹,因為對於每個物品我們有兩種處理方式(加入揹包或者不加入揹包),故該問題的解是一顆子集樹。
在前面的利用貪心演算法求解揹包問題的時候我們能得到理論的最優解,在回溯法涉及到對於子樹的剪枝的時候可以利用貪心演算法的得到的最優解(揹包問題的最優解是01揹包問題解的上界)作為我們剪枝的條件。
我們定義子集樹的左節點代表將當前物品加入揹包,右節點代表不將當前物品加入揹包。
進入左節點的條件(即加入物品到揹包):
當前物品的重量小於揹包的剩餘可容納的重量。
進入右節點的條件(即不把當前物品加入到揹包):
在不加入當前物品的情況下,剩餘節點的最大價值上界(利用貪心演算法求解)加上當前的價值小於我們求解的當前的最大價值,我們就無需考慮其右節點的情況。
#include
using
namespace
std;
float c=7; //揹包的總容量
int n=4; //物品的總件數
//預設按照單位價值從大到小排序
float w[10]=; //物品的質量 從 1 開始儲存
float v[10]=; //物品的價值 從 1 開始儲存
// 單位價值為: 5 4 3 2
float cw=0; //當前重量
float cv=0; //當前價值
float bestv=0; //當前最優價值
//利用貪心演算法取出最優解的上界限
int bound(int i)
}return tempv;
} void knip(int i)
// 當前位於節點i 判斷是否可以進入左節點
if(cw+w[i]<=c)
// 當前位於節點i 判斷是否可以進入右節點 即當前物品不加入揹包
if(bound(i+1)>bestv)
} int main()
回溯法求解0 1揹包問題
include using namespace std struct dot void getvalue int weight,int value void calculate int weight,int value else while deep 6 else int main 選擇第1個 當前...
0 1揹包問題 回溯法求解
0 1揹包問題 物品總數n,每個物品的體積w i 價值v i 給定揹包的總容量w,求放入揹包中物品的最大價值。用回溯法對0 1揹包問題進行求解,具體思路是 1.使用解空間進行標記每個物品的放入情況,即要建立乙個陣列進行儲存其是否放入,可使用 bool x i 進行標識 2.回溯法第一感覺上是窮舉所有...
演算法實驗 回溯法求解0 1揹包問題
通過剪枝和衝突,走遍所有可能的選擇,最終得到最優解 1 每個節點有兩種選擇方法,依次對所有可能的方法進行遍歷 2 在遍歷的過程中通過設定一全域性變數用來比較所有的解法的結果,最終得到最優解 lagestv 0bestx 1 2 def jianzhi i,n,c,w,ww if i n return...