简单01背包java实现

8 篇文章 0 订阅

最近看到了一道关于01背包问题的题,总之属于动态规划问题,大学时学过,现在再复习一遍。

先贴上代码,本次讨论的是最简单01背包问题,不涉及其他贪心等方面算法。

1 public class Knapsack {
 2     private final int MIN = Integer.MIN_VALUE;
 3 
 4     @org.junit.Test
 5     public void test() {
 6         int[] w = {3, 2, 2};
 7         int[] v = {5, 10, 20};
 8         knapsackOptimal(5, w, v);
 9     }
10 
11     /**
12      * 01背包-容量压缩
13      *
14      * @param c      包容量
15      * @param weight 各物品质量
16      * @param value  各物品价值
17      */
18     public void knapsackOptimal(int c, int[] weight, int[] value) {
19         int n = weight.length; //物品数量
20         int[] w = new int[n + 1];
21         int[] v = new int[n + 1];
22         int[][] G = new int[n + 1][c + 1];
23         for (int i = 1; i < n + 1; i++) {
24             w[i] = weight[i - 1];
25             v[i] = value[i - 1];
26         }
27 
28         //初始化values[0...c]=0————在不超过背包容量的情况下,最多能获得多少价值
29         //原因:如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了
30         int[] values = new int[c + 1];
31         //初始化values[0]=0,其它全为负无穷————解决在恰好装满背包的情况下,最多能获得多少价值的问题
32         //原因:只有容量为0的背包可以什么物品都不装就能装满,此时价值为0,其它容量背包均无合法的解,属于未定义的状态,应该被赋值为负无穷
33         /*for (int i = 1; i < values.length; i++) {
34             values[i] = MIN;
35         }*/
36 
37         for (int i = 1; i < n + 1; i++) {
38             for (int t = c; t >= w[i]; t--) {
39                 if (values[t] < values[t - w[i]] + v[i]) {
40                     values[t] = values[t - w[i]] + v[i];
41                     G[i][t] = 1;
42                 }
43             }
44         }
45         System.out.println("最大价值为: " + values[c]);
46         System.out.print("装入背包的物品编号为: ");
47         /*
48         输出顺序:逆序输出物品编号
49         注意:这里另外开辟数组G[i][v],标记上一个状态的位置
50         G[i][v] = 1:表示物品i放入背包了,上一状态为G[i - 1][v - w[i]]
51         G[i][v] = 0:表示物品i没有放入背包,上一状态为G[i - 1][v]
52         */
53         int i = n;
54         int j = c;
55         while (i > 0) {
56             if (G[i][j] == 1) {
57                 System.out.print(i + " ");
58                 j -= w[i];
59             }
60             i--;
61         }
62     }
63 }

关键部分在于

 for (int i = 1; i < n + 1; i++) {
38             for (int t = c; t >= w[i]; t--) {
39                 if (values[t] < values[t - w[i]] + v[i]) {
40                     values[t] = values[t - w[i]] + v[i];
41                     G[i][t] = 1;
42                 }

如果当第t件物品价值(t重量大于i)小于放入第i件物品价值时,就让价值等于第i件物品价值。

01背包问题就在于0不拿i件物品,1拿i件物品。

F[i,v]=max{F[i−1,v],F[i−1,v−Ci]+Wi}

这是最优解。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值