LintCode刷题——背包问题 III(动态规划)

题目描述

给定 n 种物品, 每种物品都有无限个. 第 i 个物品的体积为 A[i], 价值为 V[i].

再给定一个容量为 m 的背包. 问可以装入背包的最大价值是多少?

  1. 不能将一个物品分成小块.
  2. 放入背包的物品的总大小不能超过 m.
样例

样例 1:

输入: A = [2, 3, 5, 7], V = [1, 5, 2, 4], m = 10
输出: 15
解释: 装入三个物品 1 (A[1] = 3, V[1] = 5), 总价值 15.

样例 2:

输入: A = [1, 2, 3], V = [1, 2, 3], m = 5
输出: 5
解释: 策略不唯一. 比如, 装入五个物品 0 (A[0] = 1, V[0] = 1).
标签
背包型动态规划    动态规划
 

AC代码

 1 public class Solution {
 2     /**
 3      * @param A: an integer array
 4      * @param V: an integer array
 5      * @param m: An integer
 6      * @return: an array
 7      */
 8     public int backPackIII(int[] A, int[] V, int m) {
 9         // write your code here
10         int n = A.length;
11         if (m == 0 || n == 0) {
12             return 0;
13         }
14 
15         int[][] dp = new int[2][m + 1];
16 
17         dp[0][0] = 0;
18 
19         for (int i = 1; i <= 1; i++) {
20             dp[i][0] = 0;
21         }
22 
23         for (int i = 1; i <= m; i++) {
24             dp[0][i] = 0;
25         }
26 
27         // 滚动数组,减少空间复杂度
28         // 此时的空间复杂度为:O(m)
29         int old = 0;
30         int now = 1;
31         for (int i = 1; i <= n; i++) {
32             old = now;
33             now = 1 - now;
34             for (int j = 1; j <= m; j++) {
35                 if (A[i - 1] > j) {
36                    dp[now][j] = dp[old][j];
37                 } else {
38                      // 枚举可以放几个第i件物品,这里k一定要从开始,为的是后面选出最大价值时要跟dp[i - 1][j]比,如果这里不比的话,结果可能会有偏差
39                     for (int k = 0; k * A[i - 1] <= j; k++) {
40                         // 这里注意:第i件物品可能不止放一件,所以这里是要跟dp[i][j],即跟自身比,跟放k - 1件时的自己比
41                         dp[now][j] = Math.max(dp[now][j], dp[old][j - k * A[i - 1]] + k * V[i - 1]);
42                     }
43                 }
44             }
45         }
46 
47         return dp[now][m];
48     }
49 }

 

posted @ 2021-04-06 18:45  没有你哪有我  阅读(94)  评论(0编辑  收藏  举报