推薦揹包九講,很是棒。如下是我的對其前四講內容的梳理和Java實現,用於快速回顧知識點。java
問題:算法
N件物品,一個容量M的揹包。A[]是物品體積,V[]是物品價值,求揹包能裝物品的最大價值。
思路:數組
dp[i][j]表前i件物品在容量最大爲j的限制下能獲得的最大價值。
public int pack01Solution1(int m,int A[],int V[] ){ int[][] dp = new int[A.length+1][m+1]; for(int i=0;i<A.length;i++){ for(int j=0;j<=m;j++){ if(A[i]>j)dp[i+1][j] = dp[i][j]; else dp[i+1][j] = Math.max(dp[i][j],dp[i][j-A[i]]+V[i]); } } return dp[A.length][m]; }
時間複雜度O(NM),空間複雜度O(NM)。優化
空間優化爲O(M):spa
public int pack01Solution2(int m,int A[],int V[] ){ int[]dp = new int[m+1]; for(int i=0;i<A.length;i++){ for(int j=m;j>=A[i];j--){ dp[j] = Math.max(dp[j],dp[j-A[i]]+V[i]); } } return dp[m]; }
能夠把01揹包中對一件物品的處理抽取爲方法:code
public void ZeroOnePack(int cost,int value,int[] dp,int m){ for(int j=m;j>=cost;j--) dp[j] = Math.max(dp[j],dp[j-cost]+value); }
初始化的細節問題:blog
問題:圖片
N種物品,揹包容量爲M,每種無限件,給出物品體積和價值A[]、V[],求最大價值。
思路:ip
dp[i][j] = max{dp[i-1][j-k*A[i]]+k*V[i]|0<=k*A[i]<=M} 時間複雜度:有O(NM)個狀態,每一個狀態求解時間O(M/A[i]),總時間O(Σ(M/A[i])*M).
轉化爲01揹包問題:get
-第i種物品轉化爲M/A[i]件體積和價值不變的物品,複雜度不變 -第i種物品表示成2^k件物品的總和,A[i]*(2^k)<=M,每種物品可拆成O(logM/A[i])件物品 -一維數組實現的**O(NM)**算法:dp[i][j] = max{dp[i-1][j],dp[i][j-A[i]]+V[j]}
public int packComSolution(int m,int[] A,int[] V){ int[] dp = new int[m+1]; for(int i=0;i<A.length;i++){ for(int j=A[i];j<=m;j++) dp[j] = Math.max(dp[j],dp[j-A[i]]+V[i]); } return dp[m]; }
其中處理一種徹底揹包的物品能夠抽取方法:
public void CompletePack(int cost,int value,int[] dp,int m){ for(int j=cost;j<=m;j--) dp[j] = Math.max(dp[j],dp[j-cost]+value); }
問題:
在01揹包基礎上,增長條件每件物品的可取件數n[];
思路:
轉化成01揹包,每種物品的n[i]均可以用2^0,2^1,..2^(k-1),n-(2^k-1)中若干數的和表示,k是知足n[i]-2^k+1>0的最大整數。 第i種物品分紅了O(log n[i])種物品,複雜度從O(M*Σn[i])變爲O(M* Σlog n[i])
public void packMutiSolutionk(int m,int[] A,int[] V ,int[] N){ int[] dp = new int[m+1]; for(int i=0;i<A.length;i++){ MutiPack(A[i],V[i],N[i],dp,m); } } public void MutiPack(int cost, int value, int amount, int[] dp, int m){ if(cost*amount>=m){ CompletePack(cost,value,dp,m); return; } int s=1; while(s<amount){//條件:amount-s>0 ZeroOnePack(s*cost,s*value,dp,m); amount -= s; s *= 2; } ZeroOnePack(amount*cost,amount*value,dp,m); }