01背包问题的动态规划求解及其C++实现
本文講解01背包問題的動態規劃求解,并使用C++進行了實現
文章目錄
- 01背包問題
- 動態規劃
- 01背包問題的動態規劃求解
- 01背包問題的動態規劃求解-C++實現
01背包問題
有nnn個物品,這些物品的重量分別為w1,w2,...,wnw_1,w_2,...,w_nw1?,w2?,...,wn?,價值分別為v1,v2,...,vnv_1,v_2,...,v_nv1?,v2?,...,vn?.
現給定一個背包,背包的容量為CCC,要求從這個nnn個物品中選擇一些物品裝進背包,讓背包盡可能裝滿,并使得背包里裝的物品的價值最大。
要從這些物品中挑選一些裝進背包,對于某一物品而言,只有裝和不裝兩種選擇,因此稱為01背包問題
動態規劃
動態規劃是一種算法設計技術,它用來解決類似這樣的問題:
一個問題可以被分成很多個階段,而且任何一階段的行為都依賴于該階段前面的狀態,但是該階段前面的狀態是如何得來的與該階段無關。我們稱這樣的過程為多階段決策過程。
事實上,動態規劃就是解決多段決策過程最優問題的一種方法。
在使用動態規劃法求解問題時,被求解的問題應滿足最優性原則:
一個最優問題的任何實例的最優解是由該實例的子實例的最優解組成的(子問題最優,全局才能最優)。
拿斐波那契數列來說:
- 如果我們直接使用遞歸表達式求解的話回耗費很大內存且會被重復計算
- 而如果我們正向計算,把每一次計算的結果保存起來,則只需要進行加法運算,則大大地方便了計算
因此,對于交疊子問題的求解,我們也可以使用這種方式:
對交疊子問題的每個較小子問題求解一次后記錄在表中,就可以從表中得到原始問題的解
01背包問題的動態規劃求解
我們這里舉例說明背包問題的動態規劃求解
背包容量為5,各種物品的重量及價值如下:
| 1 | 2 | 12 |
| 2 | 1 | 10 |
| 3 | 3 | 20 |
| 4 | 2 | 15 |
正如前面我們所分析的,我們通過填表的方式利用動態規劃的方式求解的話能夠大大地簡化問題的求解:
我們用V(i,j)V(i,j)V(i,j)表示將前i個物品放到容量為j的背包中時最優解的物品總價值,則在裝入物品的時候我們有兩種情況:
V(i,j)=V(i?1,j)V(i,j) = V(i - 1,j)V(i,j)=V(i?1,j)
V(i,j)=max{V(i?1,j),vi+V(i?1,j?wi)}V(i,j) = max\{ V(i - 1,j),{v_i} + V(i - 1,j - {w_i})\} V(i,j)=max{V(i?1,j),vi?+V(i?1,j?wi?)}
即:
我們對背包容量為0到5填表,得到表的情況如下:
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | ||
| 2 | 12 | 1 | 0 | 0 | 12 | 12 | 12 | 12 |
| 1 | 10 | 2 | 0 | 10 | 12 | 22 | 22 | 22 |
| 3 | 20 | 3 | 0 | 10 | 12 | 22 | 30 | 32 |
| 2 | 15 | 4 | 0 | 10 | 15 | 25 | 30 | 37 |
最終的最優解為表的后一個元素37
01背包問題的動態規劃求解-C++實現
#include <iostream> using namespace std; int knapsack(int num,int capacity,int weight[],int value[]){//使用動態規劃求解0-1背包問題/*@parameters:@num:物品數量,整數類型@capacity:背包容量,整數類型@weight:各個物品的重量,數組類型@value:各個物品的價值,數組類型*/int space,sub_cap,total_value[num+1][capacity+1];for(int i=0;i<=num;i++)for(int j=0;j<=capacity;j++)total_value[i][j]=0;//初始化記憶表格for(sub_cap=1;sub_cap<=capacity;sub_cap++){for(space=1;space<=num;space++){if(sub_cap>=weight[space-1]){//判斷是否能不能裝下//能裝下,判斷裝了以后是不是背包的價值更大了total_value[space][sub_cap]=max(total_value[space-1][sub_cap],total_value[space-1][sub_cap-weight[space-1]]+value[space-1]);}else{//裝不下的話背包價值還是沒有裝之前的價值total_value[space][sub_cap]=total_value[space-1][sub_cap];}}}return total_value[num][capacity]; } int main(){int num=4,capacity=5,weight[]={2,1,3,2},value[]={12,10,20,15};cout<<knapsack(num,capacity,weight,value);return 0; }代碼的運行結果為:
37才疏學淺,難免有錯誤和不當之處,歡迎交流批評指正!
同時有問題的話歡迎留言或郵箱聯系(ljt_IT@163.com)。
總結
以上是生活随笔為你收集整理的01背包问题的动态规划求解及其C++实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 获取手机串码——手机唯一标示
- 下一篇: 1109:开关灯(C C++)