01背包打天下。
01背包 三维!- i w 01
-
记忆化递归 , 从n-1号开始,考虑与不考虑
public int bestValue(int[] w,int[] v,int n,int c){ //尝试用 n号物品 填充 c的背包 记忆化nc即可。 if(n<0 || c<=0){ return 0; }else{ int A = bestValue(w,v,n-1,c); // 不考虑当前物品 //考虑的时候 这个条件必不可少 int B = 0; if(w[n]<=c){ //能放进去才能考虑。 B = v[n] + bestValue(w,v,n-1,c-w[n]); // 考虑 } return Math.max(A,B); } } -
DP
-
重量要作为数组的下标。 重点在这。要填满。
-

-
我习惯的选与不选数组
-
dp[i] [w] [1] 就是 当前物品在w重量下 选择的最优解。
-
状态转移方程:
-
dp[i][w][0] = Math.max(dp[i-1][w][0],dp[i-1][w][1]) //不选 -
dp[i][w][1] = values[i] + Math.max(dp[i-1][w-weights[i]][0],dp[i-1][w-weights[i]][1])//选 -
很多我习惯的都可以合并。
-
-
二维DP 选与不选可合并。
-
//F(i,c) = Max( F(i-1,c) , v(i)+F(i-1,c-w(i) ) //状态转移方程 dp[i][w] = dp[i-1][w];// 不选 if(w>=weights[i]){ dp[i][w] = Math.max(dp[i-1][w],values[i]+dp[i-1][w-weights[i]]); //选与不选合并。 }
-
-
空间优化
-
F(i,c) = Max( F(i-1,c) , v(i)+F(i-1,c-w(i) ) 状态转移方程
-
第i行只依赖于i-1行。 ,只需要保留两行数据。
-
不断的覆盖前一行内容。因为后面用不到了。
-
使用奇偶行即可。 i%2
for(int i =1;i<weights.length;i++){ for(int w=0;w<=C;w++){ //F(i,c) = Max( F(i-1,c) , v(i)+F(i-1,c-w(i) ) //状态转移方程 dp[i%2][w] = dp[(i-1)%2][w];// 不选 if(w>=weights[i]){ dp[i%2][w] = Math.max(dp[(i-1)%2][w],values[i]+dp[(i-1)%2][w-weights[i]]); //选与不选合并。 } } }
-
-
空间再优化 二维转1维
-
思考,每次第二行更新的时候 只用到了第一行对应位置 左边的数据
-
那么我们就用一行,到第二个物品的时候,从右往左更新,那么就可以不断的刷新同一行即可。
-
for(int i =1;i<weights.length;i++){ //只用到了左边的数据。右边不用,那么久可以从右往左更新。 for(int w=C;w>=1;w--){ //F(i,c) = Max( F(i-1,c) , v(i)+F(i-1,c-w(i) ) //状态转移方程 dp[w] = dp[w-1];// 不选 if(w>=weights[i]){ dp[w] = Math.max(dp[w-weights[i]],values[i]+dp[w-weights[i]]); //选与不选合并。 } } } return dp[C];
-
-
题目升华,加上体积 ,那么多加一维就ok
-

浙公网安备 33010602011771号