1. 背包问题案例
贼,夜入豪宅,可偷之物甚多,而负重能力有限,偷哪些才更加不枉此行?
好,我们把它抽象化一些
给定一组多个(n)物品,每种物品都有自己的重量(Wi)和价值(Vi),在限定的总重量/总容量(C)内,选择其中若干个(也即每种物品可以选0个或1个),设计选择方案使得物品的总价值最高。
5kg的袋子
物品:物品只有一个,且不能拆分。
钱:6 10 12
Kg:1 2 4
我们把5kg袋子拆分成1kg 1kg这样的来计算,每个格子的意思就是当前袋子在这个容量下能装的最大价值。行表示每次加的物品
|
1kg |
2kg |
3kg |
4kg |
5kg |
加第一个物品 |
6 |
6 |
6 |
6 |
6 |
加第二个物品 |
6(第二个装不下,去上面第一个) |
10 |
16 10(还剩1kg) |
16 |
16 |
加第三个物品 |
6 |
10 |
16 |
16 |
18 |
第二个进来时,如果此时袋子为2kg,我们知道在第一个物品进来时,2kg最多能装6块钱。,这时候如果我们选择装第二物品那么袋子里面的钱为10块,然后剩余0kg,那么物品1就不能装了。然后发现10块大于袋子里面原来的6快,所以我们选择装第二个 丢掉第一个。
第三个物品进来,如果此时袋子为5kg,我们如果选择加第三个物品,那么袋子容积还剩1kg,能得12块,我们找到上一列1kg袋子的最大价值,为6,所以总的为18.
2. 背包问题的 Java 代码实现
package com.example.springboot1.duigui;
/*
* @author Dongxu Hua
* @date 2019/8/19 16:06
*/
public class DP {
public static void main(String[] args) {
int value[] = {60,100,120}; //每个物品的钱
int weight[] = {15,20,40}; //每个物品的重量 和上面的一一对应
int w = 50; //袋子的容积
int n = 3; //物品的个数
int dp[][] = new int[n+1][w+1]; //表示分割成一个小表格
for(int i = 1; i<=n ;i++) { //表示物品往里面加
for(int cw = 1; cw <= w; cw ++) { //袋子在每一个容积下所装的最大的钱
if(weight[i - 1] <= cw) { //表示这个物品可以装
dp[i][cw] = Math.max(
value[i-1]+dp[i-1][cw-weight[i-1]], //我装新加的物品
dp[i-1][cw] //我不装这个新加的这个物品
);
}else {
dp[i][cw] = dp[i-1][cw]; //新加的这个装不下 ,那么就取前一个物品装值
}
}
}
System.out.println("袋子能装的最大价值:" + dp[n][w]);
}
}
代码执行结构如下:
袋子能装的最大价值:160
Process finished with exit code 0