目录
背包问题:
给定一个商品重量数组weight[] , 所对应的价值数组value[] ,背包容量为bag (均为int整形)。
weight >= 0,value >= 0 ;
试问: 背包中所能装下的商品的最大价值和是多少?
思路:先用暴力递归的方法写出问题的尝试函数,通过尝试函数去套解动态规划问题。
暴力递归
我们可以用一个索引index,自左向右依次遍历商品;每遍历到一个商品时,该商品有且仅有 要或者不要 两种情况。递归并返回两种情况的最大值。
这里有几个值得注意的地方:
-
当背包剩余容量 rest<0 时:返回0;
-
当索引越界时:返回0;
-
当背包的容量 rest>0 但不足以装下当前商品时:放弃该商品;
代码如下:
//主方法
public static int BagPro (int weight[], int value[], int bag) {
if (weight==null || value == null || weight.length != value.length || weight.length==0) {
return 0;
}
return process(weight,value,0,bag);
}
//子方法
public static int process (int weight[], int value[], int index, int rest) {
//剩余容量小于0
if (rest < 0) {
return 0;
}
//索引越界
if (index == weight.length) {
return 0;
}
//不要该物品
int p1 = process(weight,value,index+1,rest);
//要该物品:先判断背包容量是否够,不够返回0;
int p2 = 0;
int next = rest-weight[index] < 0 ? -1 : value[index];
//若背包容量够,返回当前value并调用下一个商品做判断。
if (next != -1) {
p2 = next + process(weight,value,index+1,rest-weight[index]);
}
//返回一个最大value和。
return Math.max(p1,p2);
}
测试:
public static void main(String[] args) {
int[] weight = {2,4,1,2,3};
int[] value = {5,1,6,1,2};
System.out.println(BagPro(weight,value,11));
System.out.println(dp(weight,value,11));
}
//结果
14
14
动态规划
由于暴力递归的过程中存在重复解,因此可以对上述代码进行优化。写出暴力递归的尝试函数后,只需要将尝试函数作为动态规划中“缓存表”的添值方法,写出“缓存表”,即可轻松得到此背包问题的动态规划解法。
分析:在这个问题中,索引index 和 背包剩余容量rest 的值是动态变化的,因此以二者的取值范围为基础建立一张dp表,返回index==0,rest==
- index:0~weight.length(越界)
- rest:负值~bag(最大容量)
//背包问题——动态规划
public static int dp (int weight[], int value[], int bag) {
if (weight==null || value == null || weight.length != value.length || weight.length==0) {
return 0;
}
int N = weight.length;
//创建dp表
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);
}
}
return dp[0][bag];
}
测试:
public static void main(String[] args) {
int[] weight = {2,4,1,2,3};
int[] value = {5,1,6,1,2};
System.out.println(BagPro(weight,value,11));
System.out.println(dp(weight,value,11));
}
//输出:
14
14