01揹包問題我最初學會的解法是回溯法,第一反應並非用動態規劃算法去解答。緣由是學習動態規劃算法的時候,矩陣連乘、最長公共子串等問題很容易將問題離散化成規模不一樣的子問題,比較好理解,而對於01揹包問題則不容易想到將揹包容量離散化抽象出子問題,從情感上先入爲主也誤覺得動態規劃算法不是解決01揹包問題的好方法,實際上並非這樣的。另外,動態規劃算法不對子問題進行重複計算,可是要自底向上將全部子問題都計算一遍,直到計算出最終問題的結果也就是咱們要的答案,有點像登山的感受。ios
問題描述:給定n種物品和一揹包,物品i的重量是wi,其價值爲vi,揹包的容量爲C,求能裝入揹包的物品的最大價值。
用m(i,j)表示爲從i到n的物品裝入容量爲j的揹包能產生的最大價值,則能裝入揹包的物品最大價值爲m(1,C)。
遞歸式爲:算法
上面講到,該問題是對揹包的容量進行離散化,所以時間複雜度是O(nC)。學習
代碼以下(用的變量名可能和上面有小出入,可是是自描述的):spa
#include<iostream> using namespace std; struct CARGO{ int weight; int value; }; const int totalWeight=10; const int totalNumber=5; CARGO goods[totalNumber]={{2,6},{2,3},{6,5},{5,4},{4,6}}; //1.使用時下標都從1開始;2.遇到複雜結構的初始化用memset方法。 int result[totalNumber+1][totalWeight+1]={0}; int myMax(int i,int j) { return i>=j?i:j; } void dp() { int i,j; //動態規劃表達式的初始化 i=totalNumber; for(j=1;j<=totalWeight;j++) { if(goods[i-1].weight>j)//爲保證邏輯完整性,這個if沒刪掉 { result[i][j]=0; } else { result[i][j]=goods[i-1].value; } } for(i=totalNumber-1;i>0;i--) { for(j=1;j<=totalWeight;j++) { if(goods[i-1].weight>j) { result[i][j]=result[i+1][j]; } else { result[i][j]=myMax(result[i+1][j],result[i+1][j-goods[i-1].weight]+goods[i-1].value); } } } } int main() { dp(); cout<<result[1][totalWeight]<<endl; //是否理解:完成用result[totalNumber][totalWeight]表示揹包最大value的代碼(從前日後解決子問題的方法)。 return 0; }