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

题目描述

n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.

问最多能装入背包的总价值是多大?

 
  1. A[i], V[i], n, m 均为整数
  2. 你不能将物品进行切分
  3. 你所挑选的要装入背包的物品的总大小不能超过 m
  4. 每个物品只能取一次
样例

样例 1:

输入: m = 10, A = [2, 3, 5, 7], V = [1, 5, 2, 4]
输出: 9
解释: 装入 A[1] 和 A[3] 可以得到最大价值, V[1] + V[3] = 9 

样例 2:

输入: m = 10, A = [2, 3, 8], V = [2, 5, 8]
输出: 10
解释: 装入 A[0] 和 A[2] 可以得到最大价值, V[0] + V[2] = 10
挑战

O(nm) 空间复杂度可以通过, 不过你可以尝试 O(m) 空间复杂度吗?

 

背包问题 与 背包问题Ⅱ相比,前者是求最多能装多满,而后者是求价值最大为多少,其实质都是一样。都是利用动态规划求最值型问题,利用滚动数组来节省空间消耗

 

AC代码

 1 public class Solution {
 2     /**
 3      * @param m: An integer m denotes the size of a backpack
 4      * @param A: Given n items with size A[i]
 5      * @param V: Given n items with value V[i]
 6      * @return: The maximum value
 7      */
 8     public int backPackII(int m, int[] A, int[] V) {
 9         // write your code here
10         int n = A.length;
11         if (m == 0) {
12             return 0;
13         }
14 
15         // 滚动数组
16         int[][] dp = new int[n + 1][m + 1];
17 
18         // 初始化
19         dp[0][0] = 0;
20 
21         for (int i = 1; i <= n; i++) {
22             dp[i][0] = 0;
23         }
24         for (int i = 1; i <= n; i++) {
25             dp[0][i] = 0;
26         }
27 
28         // 定义两个变量,用来滚动数组
29         int old = 0;
30         int now = 1;
31         // 转移方程,先考虑物品,再考虑容量
32         for (int i = 1; i <= n; i++) {
33             old = now;
34             now = 1- now;
35             for (int j = 1; j <= m; j++) {
36                 // 求最大值,一般可以不用设置为无穷小,因为答案往往是正的,结合实际问题来分析
37                 if (A[i - 1] > j) {
38                     dp[now][j] = dp[old][j];
39                 } else {
40                     dp[now][j] = Math.max(dp[old][j], dp[old][j - A[i - 1]] + V[i - 1]);
41                 }
42             }
43         }
44 
45         return dp[now][m];
46     }
47 }

 

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