物品 | 重量(磅) | 价格 |
---|---|---|
吉他(G) | 2 | 1500 |
音响(S) | 4 | 5000 |
电脑(L) | 5 | 2000 |
- 装入的背包的总价值最大,并且重量不超出
- 装入的物品不能重复
算法介绍
- 动态规划核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解
- 动态规划与分治算法类似,基本思想也是将待求解问题分解成若干子问题,先求子问题,然后从这些子问题的解得到原问题的解
- 与分治法不同,适合于动态规划求解的问题,经分解得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)
- 动态规划算法可以通过填表的方式来逐步推进,得到最优解
背包问题
- 给定容量的背包,若干具有一定价值和重量的物品。如何选择物品使放入背包的物品价值最大。其中又分为01背包和完全背包(每种物品都有无限件可用)
- 这里的问题属于01背包,即每种物品最多放一个(0个或1个),无限背包可以转化为01背包
背包问题思路
-
每次遍历第i个物品,设W[i]和V[i]分别第i个物品的价值和重量
-
v[i] [j] 表示在前i的物品中能够放入容量为j的背包的价值最大值
1磅 2磅 3磅 4磅 吉他 1500 1500 1500 1500 音响 1500 1500 1500 3000 电脑 1500 1500 2000 2000+1500
- w[i]>j时,v[i] [j] = v[i-1] [j] //当前加入的物品容量大于背包容量,则取遍历到上一个物品时的最大装入策略
- w[i]<=j时,v[i] [j] = max(v[i-1] [j], v[i-1] [j-w[i]] + V[i])
public class DynamicProgramming {
public static void main(String[] args) {
int[] w = {1, 4, 3}; // 物品的重量
int[] val = {1500, 3000, 2000}; // 物品的价值
int m = 4; // 背包的容量
// 多垫一行一列,避免数组越界
int[][] v = new int[w.length + 1][m+1]; // v[i][j] 表示前i个物品能够装容量为j的背包的最大价值
// 因为多垫了一行一列,所以下标从1开始
for (int i = 1; i < v.length; i++) {
for (int j = 1; j < v[0].length; j++) {
if (w[i -1] > j) {
v[i][j] = v[i-1][j];
} else {
v[i][j] = Math.max(v[i - 1][j], v[i - 1][j - w[i-1]] + val[i-1]);
}
}
}
printV(v);
}
public static void printV(int[][] v) {
for (int[] val : v) {
System.out.println(Arrays.toString(val));
}
}
}
网友评论