完全背包的三个for循环的解法参考文章动态规划:完全背包 Java,01背包的解法参考文章动态规划:01背包。
01背包的状态转移函数为:Val[i][j] = max{Val[i-1][j],Val[i-1][j-w[i]+v[i]},即在背包剩余容量为 j 时,放入物品 i ,取放入物品 i 时和不放入时的最大值。
01背包为了降低空间复杂度,可以使二维数组转变为一维数组来取得优化。此种优化方法用来解决完全背包问题时,可以使三重for循环优化为两层,状态转移函数为 Val[i][j] = max{Val[i-1][j] , Val[i][j-w[i] + v[i]} ,此状态转移函数与解决01背包问题时的函数相似,利用Val[i][y-w[i]]+v[i] 取代了 Val[i-1][j-k*w[i]]+k*v[i] ,由此少了一次k的循环。
样本:
递推公式得到的Val[i][j]:
可执行代码:
package dyfu.algorithm;
public class DynamicProgram_FullBackpack2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//物品的体积
int w[] = {2,3,4};
//物品的价值
int v[] = {2,3,4};
int val[][] = new int[3][11];
val = getPerfectVal(w, v, 10);
System.out.println("The best value is "+val[2][10]);
//输出Val
/*for(int i=0;i<val.length;i++)
for(int j=0;j<val[0].length;j++)
System.out.println("val["+i+"]["+j+"]="+val[i][j]);*/
}
public static int[][] getPerfectVal(int[] w,int[] v,int capacity) {
int[][] Val = new int[w.length][capacity+1];
//第一列置0,方便计算
for(int a=0;a<w.length;a++)
Val[a][0] = 0;
//初始化Val,当i=1时,Val[1][y]仅仅与v[1]相关
for(int b=1;b<=capacity;b++)
Val[0][b] = b/w[0]*v[0];
//按01规划递推公式Val[i][j] = max{Val[i-1][j],Val[i][j-w[i]]+v[i]}
for(int i=1;i<w.length;i++)
for(int j=1;j<=capacity;j++) {
if(j>=w[i]) {
Val[i][j] = Val[i-1][j] > Val[i][j-w[i]]+v[i]?Val[i-1][j]:Val[i][j-w[i]]+v[i];
}else {
Val[i][j] = Val[i-1][j];
}
}
return Val;
}
}
运行结果: