0-1背包問題;動態規劃;時間複雜度O(n方);給出最大價值與解得情況;內有動態規劃思路總結;

來源:互聯網
上載者:User

#include <iostream><br />using namespace std;</p><p>//動態規劃:0-1背包問題<br />//bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] ) w[i]<=j<br />//bestValue[i][j]=bestValue[i+1][j] w[i]>j</p><p>class Knapsack<br />{<br />private:<br />int *weight;//物品重量數組<br />int *value;//物品價值數組<br />int numOfItems;//物品數量<br />int bagSpace;//背包容量<br />int **bestValue;//動態規劃表格,記錄bestValue[i][j]的價值,為最優價值,i表示物品i...n裝入容量為j的背包能達到的最大價值<br />int **path;//為了求出取得最優值時的解,記錄動態規劃表不同表項的選擇與否<br />public:<br />//建構函式<br />Knapsack(int numOfItems,int bagSpace)<br />{<br />weight=new int[numOfItems+1];<br />value=new int[numOfItems+1];<br />this->bagSpace=bagSpace;<br />this->numOfItems=numOfItems;</p><p>bestValue=new int* [numOfItems+1];<br />for(int i=0;i<numOfItems+1;i++)<br />{<br />bestValue[i]=new int[bagSpace+1];<br />}</p><p>path=new int* [numOfItems+1];<br />for(int i=0;i<numOfItems+1;i++)<br />{<br />path[i]=new int[bagSpace+1];<br />}<br />}<br />//輸入物品的重量與價值<br />void input()<br />{<br />int i=1;<br />while(i<=numOfItems)<br />{<br />cout<<"輸入第"<<i<<"個物品的重量"<<endl;<br />cin>>weight[i];<br />cout<<"輸入第"<<i<<"個物品的價值"<<endl;<br />cin>>value[i];<br />++i;<br />}<br />}<br />//動態規劃核心演算法<br />void knapsack()<br />{<br />//初始化遞迴最底層,即將bestValue[n][0:c]進行初始化<br />for(int i=0;i<=bagSpace;i++)<br />{<br />if(weight[numOfItems]<=i)<br />{<br />bestValue[numOfItems][i]=value[numOfItems];<br />path[numOfItems][i]=1;<br />}<br />else<br />{<br />bestValue[numOfItems][i]=0;<br />path[numOfItems][i]=0;<br />}<br />}<br />//遞推的進行動態規劃,自底向上,最終bestValue[1][bageSpace]為1-n物品放入容量bagSpace內的最大價值<br />for(int k=numOfItems-1;k>=1;k--)<br />{<br />for(int j=0;j<=bagSpace;j++)<br />{<br />bestValue[k][j]=bestValue[k+1][j];<br />path[k][j]=0;//不放入的情況<br />if(weight[k]<=j)//如果容量足夠放入當前物品<br />{<br />if(bestValue[k+1][j-weight[k]]+value[k]>bestValue[k][j])//如果放入的價值大於不放的價值<br />{<br />bestValue[k][j]=bestValue[k+1][j-weight[k]]+value[k];<br />path[k][j]=1;//那麼就選擇放入<br />}<br />}<br />}<br />}<br />}<br />//輸出最大價值,並且輸出選擇方式<br />void display()<br />{<br />//列印出bestValue[1][bagSpace],表示1...numOfItems的物品裝入容量為bagSpace的最大價值<br />int i=1;<br />int j=bagSpace;<br />cout<<"最大價值為"<<bestValue[1][j]<<endl;<br />//根據path[1][bagSpace]的記錄開始,遞迴到path[n][某容量],從而列印出每個物品是否被選擇進入背包<br />while(i<=numOfItems)<br />{<br />if(path[i][j]==0)//如果i物品沒被放入,看i+1個物品裝入容量j背包<br />{<br />++i;<br />}<br />else<br />{<br />cout<<"<重量:"<<weight[i]<<",價值:"<<value[i]<<">"endl;<br />j-=weight[i];<br />++i;<br />}<br />}<br />}<br />};</p><p>void main()<br />{<br />Knapsack test(5,50);//5個物品,背包容量50<br />test.input();//輸入5個物品的價值與重量<br />test.knapsack();//動態規劃<br />test.display();//列印選擇與最大價值<br />}

 

 

思路總結: 看到一個題目,首先看問什麼,下面以此題舉例分析一下。

0-1背包問題

1,問題要求什嗎? 
答:求把n個物品放入容量C的背包內能達到的最大價值

2,轉換成一個抽象一點的數學運算式是什嗎? 
答:bestValue[n][C],表示n個物品放入容量C的背包的最大價值

3,不考慮演算法應該怎麼選擇,我們實際去解決這個問題的時候,是從哪裡開始去做的?
答:我們有n個物品,C容量背包。  於是我們開始解決問題,我先放第一個物品,如果能放進去,我就放進去,當然,我也可以不放。
第一個物品處理結束以後,我們著手於第二個物品,能放進去就放進去,當然,我們也可以不放。 
所以,這就是一個決策問題,決策是從我們實際處理問題中抽象出來的,我們放物品的時候只能一個一個放,決策是放或者不放。

4,在決策瞭解的情況,我們應該考慮當前要求的bestValue[n][C],在決策放入或者不放入的情況,分別等於什麼?
答:如果能夠放入,那麼我們的背包還有C-w[i], 物品還有n-1個,當然,我們也可以選擇不放進去,那麼我們背包依舊有C容量,物品還有n-1個。 所以我們修改一下我們對bestValue[n][C]的定義,從而就得到了一個最優子結構的遞迴公式。

為了我們決策的進行,即我們每次決策都是最第i個物品進行決策,所以bestValue[n][C]修改為best[i][C],表示i,i+1,i+2...n個物品放入容量為C的背包的最大價值。

所以:bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] )  w[i]<=j
         bestValue[i][j]=bestValue[i+1][j]        w[i]>j

意思是:
如果當前容量j裝不下物品i,那麼i到n裝入j的最大價值就等於i+1到n裝入j的最大價值,就是公式的第二行。
如果當前容量j可以裝下物品i,那麼我們可以裝進去,當然,也可以犯賤,不裝進去,看看結果如何,所以i到n個物品裝入j容量背包的最大價值就等於 i+1到n物品裝入j-w[i]容量的背包可以達到的最大價值+value[i] ,i+1到n物品裝入j容量背包的最大價值,這兩種不同決策的一個最大值。

總結:解決什麼?  從哪裡開始做起?  有哪些決策?  決策後會怎麼樣?

 

找出了遞迴式,它具有最優子結構性質,即可以簡單的理解為:當前的最優產生於子問題的最優,然後子問題的最優不受當前最優的影響,並且通過觀察遞迴公式,應該找到遞迴的最底層的i,j分別是什麼,我們觀察到i在逐漸增加,j在逐漸減小,所以我們在遞推的時候,首先把最底層進行初始化,然後利用遞迴公式向上遞推。 所以我們需要首先初始化bestValue[n][0:C],即記錄第n個物品裝入0到C的背包的能達到的價值,當w[n]<=j時,bestValue[n][j]等於value[n],如果w[n]>j,即容量不夠,那麼就是0.

 

我們能夠從底向上遞推的重要原因就是:最優子結構+無後效性 。 多多體會吧。 這是基礎理解了。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.