零一背包与完全背包
零一背包
给定一组物品,每个物品有自己的重量和价值,以及一个背包的容量。目标是选择一些物品放入背包中,使得在不超过背包容量的情况下,背包中物品的总价值最大化。
思路
1、定义问题dp[i][j]:表示前i个物品中当容量为j时的最大价值
2、定义状态转移方程
(1) Dp[i][j] = math.max(dp[i][j-1], values[i] + dp[i - 1][j - weights[i]])
(2) 表示:如果放则为values[i] + dp[i - 1][j - weights[i]],如果不放则为之前计算好且容量为j-1时的最优解
3、定义初始值:dp[i][j]初始化为0,表示不放入物品时,背包的最大价值为0
代码
public class ZeroOneKnapsack { public static int knapsack(int[] weights, int[] values, int capacity) { int n = weights.length; int[][] dp = new int[n+1][capacity+1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= capacity; j++) { if (weights[i-1] <= j) { dp[i][j] = Math.max(values[i-1] + dp[i-1][j-weights[i-1]], dp[i-1][j]); } else { dp[i][j] = dp[i-1][j]; } } } return dp[n][capacity]; } public static void main(String[] args) { int[] weights = {2, 3, 4, 5}; int[] values = {3, 4, 5, 6}; int capacity = 8; int maxTotalValue = knapsack(weights, values, capacity); System.out.println("Maximum total value: " + maxTotalValue); } }
完全背包
在完全背包问题中,同样有一个背包容量为C,以及一组物品,每个物品有自己的重量和价值。不同的是,每个物品可以选择无限次放入背包中。目标是选择物品放入背包中,使得在不超过背包容量的情况下,背包中物品的总价值最大化。
思路
1、定义问题dp[j]:表示容量为j时可放入的最大价值
2、定义状态转移方程:
(1) Dp[j] = max(dp[j], values[i] + dp[j - weights[i]])
(2) 表示如果不放则为之前定义好且容量为j时的最优解,如果放则为values[i] + dp[j - weights[i]]
3、定义初始值:
代码
public class UnboundedKnapsack { public static int knapsack(int[] weights, int[] values, int capacity) { int n = weights.length; int[] dp = new int[capacity+1]; for (int i = 0; i <= capacity; i++) { for (int j = 0; j < n; j++) { if (weights[j] <= i) { dp[i] = Math.max(dp[i], values[j] + dp[i-weights[j]]); } } } return dp[capacity]; } public static void main(String[] args) { int[] weights = {2, 3, 4, 5}; int[] values = {3, 4, 5, 6}; int capacity = 8; int maxTotalValue = knapsack(weights, values, capacity); System.out.println("Maximum total value: " + maxTotalValue); } }
总结
零一背包与完全背包的max区别在于不放时的场景
(1) 零一背包:dp[i-1][j]表示不放那就最大值依赖于前i-1个物品的最大值
(2) 完全背包:dp[i]表示不放那就依赖于之前已经计算好的容量为i时的最优解
Linux等环境软件安装