给定两个长度都为N的数组weights和values,
weights[i]和values[i]分别代表 i号物品的重量和价值。
给定一个正数bag,表示一个载重bag的袋子,
你装的物品不能超过这个重量。
返回你能装下最多的价值是多少?
递归:
package code03.动态规划_07;
/**
* 给定两个长度都为N的数组weights和values,
* weights[i]和values[i]分别代表 i号物品的重量和价值。
* 给定一个正数bag,表示一个载重bag的袋子,
* 你装的物品不能超过这个重量。
* 返回你能装下最多的价值是多少?
*/
public class BagMaxValue_03 {
public static int maxValue(int[] weight, int[] value, int bag)
{
if (weight == null || weight.length == 0
|| value == null || value.length == 0 || bag < 0) {
return 0;
}
return func(weight, value, bag, 0);
}
public static int func(int[] weight, int[] value, int bag, int index)
{
//数组已经结束了,没有货物了
if (index == weight.length) {
return 0;
}
int result1 =func(weight, value, bag, index + 1);
int result2 = 0;
//大于等于0,背包是能够容纳当前货物的
if (bag - weight[index] >= 0) {
result2 = value[index] + func(weight, value, bag-weight[index], index + 1);
}
return Math.max(result1,result2);
}
public static void main(String[] args)
{
int[] weight = { 3, 2, 4, 7, 3, 1, 7 };
int[] value = { 5, 6, 3, 19, 12, 4, 2 };
int bag = 15;
int result = maxValue(weight, value, bag);
System.out.println(result);
}
}
递归 + 动态规划
package code03.动态规划_07;
/**
* 给定两个长度都为N的数组weights和values,
* weights[i]和values[i]分别代表 i号物品的重量和价值。
* 给定一个正数bag,表示一个载重bag的袋子,
* 你装的物品不能超过这个重量。
* 返回你能装下最多的价值是多少?
*/
public class BagMaxValue_03_opt1 {
public static int maxValue(int[] weight, int[] value, int bag)
{
if (weight == null || weight.length == 0
|| value == null || value.length == 0 || bag < 0) {
return 0;
}
int[][] dp = new int[weight.length][bag+1];
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < dp[i].length; j++) {
dp[i][j] = -1;
}
}
return func(weight, value, bag, 0, dp);
}
public static int func(int[] weight, int[] value, int bag, int index, int[][] dp)
{
//数组已经结束了,没有货物了
if (index == weight.length) {
return 0;
}
if (dp[index][bag] != -1) {
return dp[index][bag];
}
int result1 =func(weight, value, bag, index + 1, dp);
int result2 = 0;
//大于等于0,背包是能够容纳当前货物的
if (bag - weight[index] >= 0) {
result2 = value[index] + func(weight, value, bag-weight[index], index + 1, dp);
}
int maxResult = Math.max(result1,result2);
//放入缓存
dp[index][bag] = maxResult;
return maxResult;
}
public static void main(String[] args)
{
int[] weight = { 3, 2, 4, 7, 3, 1, 7 };
int[] value = { 5, 6, 3, 19, 12, 4, 2 };
int bag = 15;
int result = maxValue(weight, value, bag);
System.out.println(result);
}
}
动态规划
package code03.动态规划_07;
/**
* 给定两个长度都为N的数组weights和values,
* weights[i]和values[i]分别代表 i号物品的重量和价值。
* 给定一个正数bag,表示一个载重bag的袋子,
* 你装的物品不能超过这个重量。
* 返回你能装下最多的价值是多少?
*/
public class BagMaxValue_03_opt2 {
public static int maxValue(int[] weight, int[] value, int bag)
{
if (weight == null || weight.length == 0
|| value == null || value.length == 0 || bag < 0) {
return 0;
}
int N = weight.length;
int[][] dp = new int[N + 1][bag + 1];
for (int index = N - 1; index >= 0; index--) {
for (int rest = 0; rest <= bag; rest++) {
//以下逻辑完全照抄递归逻辑
int p1 = dp[index + 1][rest];
int p2 = 0;
int next = rest - weight[index] < 0 ? -1 : dp[index + 1][rest - weight[index]];
if (next != -1) {
p2 = value[index] + next;
}
dp[index][rest] = Math.max(p1, p2);
}
}
//为什么返回的是dp[0][bag], 也是完全照抄递归的参数。递归
//方法给的什么值,动态规划中就返回什么值。
return dp[0][bag];
}
public static void main(String[] args)
{
int[] weight = { 3, 2, 4, 7, 3, 1, 7 };
int[] value = { 5, 6, 3, 19, 12, 4, 2 };
int bag = 15;
int result = maxValue(weight, value, bag);
System.out.println(result);
}
}
总结:
1. 动态规划逻辑,完全照抄递归方法内部逻辑。想要写好动态规划,一个好的递归是关键
2. 递归方法传入的参数初始值是什么,那么动态规划返回的数组下标就需要一一对应。前面写了2篇博客,细心的童鞋可以去查看
3. 动态规划的二维数组中,行对应的都是数组,而列对应的是剩余的可变参数。上一篇的对应的是剩余步数、本篇对应的是bag的剩余容量