0-1揹包問題:ios
有編號分別爲a,b,c,d,e的五件物品,它們的重量分別是2,2,6,5,4,它們的價值分別是6,3,5,4,6,如今給你個承重爲10的揹包,如何讓揹包裏裝入的物品具備最大的價值總和?c++
這個問題用窮舉法固然能夠作,可是用動態規劃所用的時間花銷更少。要用一個二維數組存儲局部最優值,最後達到總的最優值,能夠說是用空間換時間,很是的經典!若是想真正理解動態規劃的思想,就把下面的程序的執行過程在本身的腦海中想一遍,結合程序運行結果圖好好的思考一下,看看運行結果圖裏面的二維數組是如何生成的,雖然會花費一些時間,可是理解後對之後的編程是大有裨益的。編程
直接貼c++代碼:數組
//動態規劃 本程序是自底向上自左向右更新最優值 #include<iostream> using namespace std; int main() { int c=10; //總的承重量,好像沒有用到,由於j也能夠表示 int m[6][11]={0}; // 第一行與第一列不用,方便編程,表示須要更新的二維數組 int w[6]={0,2,2,6,5,4}; //多寫個0方便編程,物品的重量 int v[6]={0,6,3,5,4,6}; //物品的價值 for(int i=5;i>=1;i--) //循環五次,動態嘗試放入五個物品 for(int j=1;j<=10;j++) { if(i==5) //最後一行不依賴其它行更新最優值,由於表示的是第一個放入揹包的物品 { if(w[5]<=j) {m[i][j]=v[5];} } else{ if(w[i]>j) //動態規劃核心,此式子選擇動態更新局部最優值 { m[i][j]=m[i+1][j]; //動態規劃核心,此式子選擇動態更新局部最優值 } else { m[i][j] =m[i+1][j]>m[i+1][j-w[i]]+v[i]?m[i+1][j]:m[i+1][j-w[i]]+v[i]; //動態規劃核心,此式子選擇動態更新局部最優值,
//等價於m[i][j]=max{m[i+1][j],m[i+1][j-w[i]]+v[i]} } } } cout<<m[1][10]<<endl;//輸出最大價值總和,由於本程序是自底向上自左向右更新最優值,因此最大價值總和在第一行第十列(右上角)。 for(int i=1;i<=5;i++) //循環輸出更新後的二維數組 for(int j=1;j<=10;j++){ cout<<m[i][j]; cout<<" "; if(j==10) cout<<endl; } return 0; }
運行效果圖以及自底向上自左向右更新後的二維數組以下:最大總價值爲15spa
至此最大價值咱們求出來了是15,還要解決一個問題:有哪些貨物是被選進去了呢?這個問題要用回溯法!就是從程序執行末尾開始code
從運行結果圖可知:m[1][10]=15>m[1+1][10]=11,物品一選中,剩餘重量:15-物品一的重量=10-2=8 blog
m[2][8]=9>m[3][8]=6,物品二選中,剩餘重量:8-物品二的重量=8-2=6 //注意到沒?m[2][8]中的8就是上一步的剩餘重量io
m[3][6]=6=m[4][6]=6,物品三沒選中,剩餘重量:仍是6class
m[4][6]=6=m[5][6]=6,物品四沒選中,剩餘重量:仍是6stream
m[5][6]!=0,物品五選中
綜上:所選物品有物品1,2,5總價值爲15.