问题引入:背包有固定容量,物品体积不同,价值不同,且同种物品只能够被放入一次,在不超过背包容量情况下求解背包能放入物品的最大价值。
为什么使用动态规划:物品有不同的体积,不同的价值,所以有多种物品的组合,既然有多组合,则要求出放入背包内物品组合的最优解。
首先要了解使用回溯法的两个必备条件:1.原问题具备重叠子问题 2.具有最优子结构的性质(此处可先做简单了解,理解完代码之后会融会贯通)
我对两个必备条件的理解:
原问题具备重叠子问题 :原问题内的某个小问题会被重复计算。
具有最优子结构的性质:子问题相互独立且子问题的最优解可以推出原问题的最优解
因为存在不用的子问题,所以要将每种情况都单独求解 ,使用表格的形式可以更加直观的看出每种选择的结果。
代码求解:
public class Main {
public static void main(String[] args) {
//DP动态规划问题之01背包
int[] v = {0,2,3,4,5};//物品价值
int[] w = {0,2,1,3,2};//物品体积
int bagv = 9;//背包容量
int[][] temp = new int[v.length][bagv];
for(int i = 0;i<v.length;i++){
for(int y = 0;y < bagv;y++){
temp[i][y] = 0;
}
}
//问题存在重复性,所以求解最优子结构
for(int i = 1;i <= 4;i++){
for(int j = 1;j < bagv;j++){
//判断当前物品体积是否大于当前背包体积
if(j<w[i]){
//当前物品体积大于背包体积时,则不能放入,最优解是上一个物品时,背包容量为w[j]时背包内的价值
temp[i][j] = temp[i-1][j];
}else {
//可以放入时,有两种情况,放入或不放入,需要比较两种情况哪种使包内价值更高
//temp[i-1][j]是不放入此物品,就返回选上一物品时的最优解,不用考虑包容量问题
//temp[i-1][j-w[i]]+v[i]是放入此物品,需考虑包容量,则价值为:当前物品价值+上一物品的最优解
//j-w[i]是放入当前物品后包内剩余容量,包容量的每个最优解都有记录,相加即可
temp[i][j] = max(temp[i-1][j],temp[i-1][j-w[i]]+v[i]);
}
}
}
printArr1(temp);
}
//打印方法
public static void printArr1(int[][] arr) {
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
}
//二者取最大
private static int max(int x,int y) {
if(x>=y){
return x;
}else {
return y;
}
}
}
运行结果:
由计算结果可知,14是背包所能放入物品的最大价值。
作者才疏学浅,欢迎大家矫枉指正!!!