1、01背包是解決什么問題?
答:當書包容量大小固定,面對1堆重量固定而且帶有價格的物品。在不超出包容量前提下,選擇那些物品使包里物品總價值最大。
2、問:為什么01背包?
答:因為0表示不將物品放進包里,1表示將物品放進包里。
放:意味着包的容量減小,總價值增大。
不放:意味着包容量不變,總價值不變。
3、引入題目幫助分析
3.1、 題目:01背包問題描述:有編號分別為a,b,c,d,e的N=5件物品,它們的重量w分別是2,2,6,5,4,它們的價值v分別是6,3,5,4,6,每件物品數量只有一個,現在給你個承重為M=10的背包,如何讓背包里裝入的物品具有最大的價值總和sum_v?
3.2、上面題目反映到下面表格。下面表格1-10是容量,每格容量下面是最大價值。
3.2、表格是怎樣推算出來的?
第一步:將物品排列起來,從最大容積最后一個物品開始推算(即從下往上,從右往左)
問:e(10) = 15 是什么意思? 背包容量10,從e物品開始往上取物品,能取到最大價值是15。那么15是怎樣推算的?
答:下圖推算最大價值15。1-10每個格子最大價值都是這樣計算。這樣把表都算好了,最大價值就一目了然。
四、通過代碼實現
參考:https://jingyan.baidu.com/album/414eccf66d98dc6b421f0a6d.html?picindex=1
問題描述:給定n種物品和一背包。物品i的重量是w[i],其價值為v[i],背包的容量為C。問應如何選擇裝入背包的物品,使得裝入背包中物品的總價值最大?
分析:對於一種物品,要么裝入背包,要么不裝。所以對於一種物品的裝入狀態可以取0和1。設物品i的裝入狀態為xi,xi∈ (0,1),此問題稱為0-1背包問題。
數據:物品個數n=5,物品重量w[5]={2,2,6,5,4},物品價值v[5]={6,3,5,4,6},總重量c=10。背包的最大容量為10,那么在設置數組m大小時,可以設行列值為5和10,那么,對於m(i,j)就表示可選物品為i到n且背包容量為j(總重量)時背包中所放物品的最大價值。看下面這個表格即為動態規划法解0-1背包問題的過程:
public class KnapsackDemo { public static void main(String []args) { System.out.println("KnapsackDemo!!!"); int[] w = {2,2,6,5,4}; int[] v = {6,3,5,4,6}; int c = 10; int[][] m; int[] x; m = KnapsackDemo.knapsack(w,v,c); x = KnapsackDemo.buileSolution(m,w,c); for(int i=0;i<4;i++){ System.out.print(x[i]+" "); } } //0-1背包問題的算法 public static int[][] knapsack(int[] w,int v,int c){ int i,j,n = w.length int[][] m = new int[n+1][c+1]; for(i=1;i<n+1;i++){ m[i][0]=0; } for(j=0;j<c+1;j++){ m[0][j]=0; } int count=0; for(i=1;i<=n;i++){ for(j=1;j<=c;j++){ m[i][j] = m[i-1][j]; if(w[i-1]<=j){ if(v[i-1]+m[i-1][j-w[i-1]]>m[i-1][j]){ m[i][j]=v[i-1]+m[i-1][j-w[i-1]]; } } count++; } } System.out.println(count); return m } //依據m[][]實現對符合結果要求的物品進行選擇的構建一個數組存儲選擇的情況0否1選擇 public static int[] buileSolution(int[][] m,int[] w,int c){ int i,j = c,n = w.length; int[] x = new int[n]; for(i=n;i>=1;i--){ if(m[i][j]==m[i-1][j]){ x[i-1] = 0; }else{ x[i-1]=1; j -= w[i-1]; } } return x; } }