package cn.com.suanfa;
/**
* @ClassName: DP01
* @Desc: 动态规划求解0-1背包问题 <br>
* 1.动态规划的核心思想: 将大问题分解成小问题,从而一步步获取最优解的处理算法(有局部最优解退出全局最优解)<br>
* 2.动态规划与分治的相同点: 将大问题分分解成小问题,通过解决小问题,来解决原问题 <br>
* 3.动态规划与分治的不同: 动态规划各个小问题之间存在着联系,分治算法,咯咯咯小问题之间相互独立 <br>
* 4.动态规划可通过填表的方式获得<br>
* @author: lancelan
* @date: 2022年12月2日 下午4:57:25 <br>
*
*/
public class DP01 {
// 定义重量的数组
public static int[] W = { 1, 4, 3 };
// 定义物品的价值
public static int[] VAL = { 1500, 3000, 2000 };
// 定义不同重量的最大价值
public static int N = 5;// 定义背包的容量
// // 定义重量的数组
// public static int[] W = { 1, 4, 3,5,7 };
// // 定义物品的价值
// public static int[] VAL = { 1500, 3000, 2000,233,987 };
// // 定义不同重量的最大价值
// public static int N = 10;// 定义背包的容量
public static void main(String[] args) {
/**
* 初始化。i行:物品,j列:背包容量,
*/
int[][] dp = new int[W.length + 1][N + 1]; // 列为背包,行为物品
int[][] resource = new int[W.length + 1][N + 1]; // 存放物品
String[][] goodsAndValue = new String[W.length + 1][N + 1];
for (int i = 0; i <= N; i++) {
goodsAndValue[0][i] = "";
}
for (int i = 0; i <= VAL.length; i++) {
goodsAndValue[i][0] = "";
}
/**
* //开始求解二维数组dp
*/
for (int goods = 1; goods <= W.length; goods++) {
for (int bagWeight = 1; bagWeight <= N; bagWeight++) {
// 如果当前背包的容量小于第i个商品的重量,将上一行的值,复制到当前行
if (bagWeight < W[goods - 1]) {
dp[goods][bagWeight] = dp[goods - 1][bagWeight];
goodsAndValue[goods][bagWeight] = goodsAndValue[goods - 1][bagWeight];
} else {// 否则背包容量大于当前商品的重量
/**
* 如果当前商品的价值+背包减去当前商品的重量后,剩余容量的价值 > 上一行的价值,就将上一行的价值赋给当前行
*/
// 当前商品价值
int curGoodsValue = VAL[goods - 1];
// 当前商品的重量
int curWeight = W[goods - 1];
// 剩余空间=当前背包容量 - 当前商品重量. 可能是0.
int leftWeight = bagWeight - curWeight;
// 剩余空间的最大价值。根据剩下空间去查找最大价值。
// 就是上一行中的
int leftValue = dp[goods - 1][leftWeight];
// 上一行的价值
int lastValue = dp[goods - 1][bagWeight];
if (curGoodsValue + leftValue > lastValue) {
dp[goods][bagWeight] = curGoodsValue + leftValue;
resource[goods][bagWeight] = 1;
goodsAndValue[goods][bagWeight] = "物品:" + goods + "-价值:" + curGoodsValue + "," + goodsAndValue[goods - 1][leftWeight];
} else { // 小于上一行的价值,使用上一行替换
dp[goods][bagWeight] = dp[goods - 1][bagWeight];
goodsAndValue[goods][bagWeight] = goodsAndValue[goods - 1][bagWeight] + "";
}
}
}
}
System.out.print("物品|");
for (int i = 0; i <= N; i++) {
System.out.print(" 容量" + (i) + "|");
}
System.out.println();
for (int i = 0; i < dp.length; i++) {
System.out.print("物品" + i + ": ");
for (int j = 0; j < dp[1].length; j++) {
System.out.print(dp[i][j] + " | ");
}
System.out.println();
}
System.out.println("----------------------------------");
for (int i = 0; i < goodsAndValue.length; i++) {
System.out.print("物品" + i + ": ");
for (int j = 0; j < goodsAndValue[1].length; j++) {
System.out.print(goodsAndValue[i][j] + " | ");
}
System.out.println();
}
System.out.println("----------------------------------");
int i = resource.length - 1;
int j = resource[0].length - 1;
while (i > 0 && j > 0) {
if (resource[i][j] == 1) {
System.out.printf("第%s个商品放到背包中\n", i);
j -= W[i - 1];// 减掉当前商品的重量,为剩余重量
}
i--;
}
}
}
结果: