0-1背包问题滚动数组解法
有n件物品和一个最多能装重量为w的背包,第i件物品的重量是weight[i],得到的价值为value[i]。每件物品只能使用一次,求解将哪些物品装入背包中物品的价值总和最大。
动态规划-滚动数组的方式解决
使用动态规划解决0-1背包问题时,定义的dp数组可以是一个二维数组,即dp[i][j]表示在0-i件物品中挑选,背包容量为j可获取的最大价值。
实际上,dp数组也可以定义为一维数组。
dp[j]表示背包容量为j的背包可装的最大价值。
dp数组转换为一维数组后,有几个需要注意的问题:
- 实际上,在遍历物品中,每一层的循环都会重新初始化dp数组,因此下一层的背包容量的循环,使用的dp数组是上一层进行过初始化的数组。
- 只能先遍历物品再遍历背包容量
- 遍历背包容量时需要倒序,因此如果正序遍历背包容量的话,会出现重复装入一个物品的情况。
动态规划步骤:
- (1)dp[j]表示背包容量为j可装的最大价值
- (2)递推公式:dp[j] = Math(dp[j],dp[j - weighjt[i]] + value[i]),dp[j]在上一层循环中重新初始化
- (3)dp数组初始化:每一层循环dp数组都会重新初始化,所以dp数组不用再进行初始化
- (4)遍历顺序:先正序遍历物品,再倒序遍历背包容量即可
- (5)模拟dp数组
代码实现
public static void main(String[] args) {
int[] weight = {1, 3, 4};
int[] value = {15, 20, 30};
int bagWight = 4;
testWeightBagProblem(weight, value, bagWight);
}
public static void testWeightBagProblem(int[] weight, int[] value, int bagWeight){
int wLen = weight.length;
//定义dp数组:dp[j]表示背包容量为j时,能获得的最大价值
int[] dp = new int[bagWeight + 1];
//遍历顺序:先遍历物品,再遍历背包容量
for (int i = 0; i < wLen; i++){
for (int j = bagWeight; j >= weight[i]; j--){
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
}
}
//打印dp数组
for (int j = 0; j <= bagWeight; j++){
System.out.print(dp[j] + " ");
}
}