動態規划01背包實現:
借鑒的這篇博文:
https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html
題目:在背包容量為8的情況下,根據下圖的數據動態規划得到最優解,實現右圖所示的程序代碼
最重要的就是尋找遞推關系式:
定義V[i,j]:當背包容量為j時,前i個物品最佳組合對應的值。
遞推關系:
(1)當背包的容量不允許裝入第i件物品時,和前一個物品裝入背包一樣。即 :V[i][j]=V[i-1][j]
(2)當背包的容積可以裝入第i件物品時,分兩種情況,A裝入第i件物品不是最優,還不如不裝。B裝入第i件物品是最優。即:V[i][j]=max(V[i-1][j],V[i][j-w[i]]+v[i])
代碼實現:
#include<iostream> using namespace std; int w[5]={0,2,3,4,5}; int v[5]={0,3,4,5,6}; int V[5][9]; int c=8; int B() { int i,j; for(i=0;i<5;i++) { V[i][0]=0; for(j=0;j<c+1;j++) { V[0][j]=0; if(j<w[i]) V[i][j]=V[i-1][j]; else V[i][j]=max(V[i-1][j],V[i-1][j-w[i]]+v[i]); } } } int main(){ B(); //顯示填好的表格 for (int i=0;i<5;i++) { for(int j=0;j<9;j++) { cout<<V[i][j]<<" "; } cout<<endl; } cout<<"最優結果是:"<<V[4][8]; return 0; }
下面是帶上回溯找出解的組成的代碼:
#include<iostream> using namespace std; int w[5]={0,2,3,4,5}; int v[5]={0,3,4,5,6}; int V[5][9]; int c=8; int item[4]; int B() { int i,j; for(i=0;i<5;i++) { V[i][0]=0; for(j=0;j<c+1;j++) { V[0][j]=0; if(j<w[i]) V[i][j]=V[i-1][j]; else V[i][j]=max(V[i-1][j],V[i-1][j-w[i]]+v[i]); } } } void FindWhat(int i,int j)//尋找解的組成方式 { if(i>=0) { if(V[i][j]==V[i-1][j])//相等說明沒裝 { item[i]=0;//全局變量,標記未被選中 FindWhat(i-1,j); } else if( j-w[i]>=0 && V[i][j]==V[i-1][j-w[i]]+v[i] ) { item[i]=1;//標記已被選中 FindWhat(i-1,j-w[i]);//回到裝包之前的位置 } } } int main(){ B(); //顯示填好的表格 cout<<"得到的表格如下圖所示:"<<endl; for (int i=0;i<5;i++) { for(int j=0;j<9;j++) { cout<<V[i][j]<<" "; } cout<<endl; } cout<<"最優結果是:"<<V[4][8]<<endl; FindWhat(4,8); cout<<endl; cout<<"回溯得到的解是:"<<endl; for(int i=1;i<5;i++){ if(item[i]==1) cout<<"背包里面有第"<<i<<"號物品"<<endl; //cout<<item[i]<<" "; } return 0; }
貼上結果便於理解:
時間復雜度:
O(物體個數*背包容積)=O(number*capacity)
空間復雜度:
用二維表實現的,所以和時間復雜度一樣。
O(物體個數*背包容積)=O(number*capacity)