动态规划--背包问题1

92. 背包问题

在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i]

样例

如果有4个物品[2, 3, 5, 7]

如果背包的大小为11,可以选择[2, 3, 5]装入背包,最多可以装满10的空间。

如果背包的大小为12,可以选择[2, 3, 7]装入背包,最多可以装满12的空间。

函数需要返回最多能装满的空间大小。

挑战

O(n x m) time and O(m) memory.

O(n x m) memory is also acceptable if you do not know how to optimize memory.

注意事项

你不可以将物品进行切割。

题目链接:https://www.lintcode.com/problem/backpack/description

昨天看了一天的动态规划的讲解,但是纸上得来终觉浅,所以今天打算进行刷题,希望能够搞懂这一类题目的做法。

解题思路:解决动态规划问题,最重要的是列出状态方程,列出来之后,问题就差不多解决了一半了。自己看了这么多的基础知识讲解,遇上之后还是有点束手无策。我想到的是对i个变量“选还是不选”,于是我开始沿着自己的思路往下做,画了一颗二叉树(就是选还是不选)。但是自己画的这个二叉树实在过于庞大(数据大的话,无法形容)而且特别复杂。肯定是自己在思路上有了差错。

自己实在做不出来,就去网上百度了一下大佬的思路。在这里分享一下:

本题是典型的01背包问题,每种类型的物品最多只能选择一件。

1.状态: result[i][S] 表示前i个物品,取出一些物品能否组成体积和为S的背包

2.状态转移方程: f[i][S]=f[i−1][S−A[i]] or f[i−1][S] (A[i]为第i个物品的大小)

1.欲从前i个物品中取出一些组成体积和为S的背包,可从两个状态转换得到。

i.f[i−1][S−A[i]]:放入第i个物品,前i−1 个物品能否取出一些体积和为 S−A[i] 的背包。

ii.f[i−1][S]:不放入第i个物品,前i−1 个物品能否取出一些组成体积和为S的背包。

3.状态初始化: f[1⋯n][0]=true; f[0][1⋯m]=false. 前1~n个物品组成体积和为0的背包始终为真,其他情况为假。

4.返回结果: 寻找使 f[n][S] 值为true的最大S (1≤S≤m)

来源:https://zhuanlan.zhihu.com/p/32001408

根据思路,状态方程如下:

这里写图片描述

自己的代码:

 public static int dp_bag(int[] arr,int m){
        int len = arr.length;
        int[][] bag_arr = new int[len][m+1];
        for(int i=0;i<len;i++)
            bag_arr[i][0] = 0;//背包的容量为0时,肯定不能放任何东西
        for(int j = 1;j<m+1;j++){
            if(arr[0]>j)//对i=0提前处理,防止发生数组越界问题
                bag_arr[0][j] = 0;
            else
                bag_arr[0][j] = arr[0];
            for(int i=1;i<len;i++){
                if(arr[i]>j){
                    bag_arr[i][j] = bag_arr[i-1][j];
                }else{
                    bag_arr[i][j] = Math.max(bag_arr[i-1][j-arr[i]]+arr[i],bag_arr[i-1][j]);
                }
            }
        }
        /*for(int i=0;i<len;i++){
            for(int j=0;j<m+1;j++)
                System.out.print(bag_arr[i][j]+" ");
            System.out.println();
        }*/
        return bag_arr[len-1][m];
    }

别人的代码:

public class Solution {
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    public int backPack(int m, int[] A) {
        boolean f[][] = new boolean[A.length + 1][m + 1];
        for (int i = 0; i <= A.length; i++) {
            for (int j = 0; j <= m; j++) {
                f[i][j] = false;
            }
        }
        f[0][0] = true;
        for (int i = 1; i <= A.length; i++) {
            for (int j = 0; j <= m; j++) {
                f[i][j] = f[i - 1][j];
                if (j >= A[i-1] && f[i-1][j - A[i-1]]) {
                    f[i][j] = true;
                }
            } // for j
        } // for i
        
        for (int i = m; i >= 0; i--) {
            if (f[A.length][i]) {
                return i;
            }
        }
        
        return 0;
    }
}


// O(m) 空间复杂度的解法
public class Solution {
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    public int backPack(int m, int[] A) {
        int f[] = new int[m + 1];

        for (int i = 0; i < A.length; i++) {
            for (int j = m; j >= A[i]; j--) {
                f[j] = Math.max(f[j], f[j - A[i]] + A[i]);
            } 
        }
        return f[m];
    }
}

来源:https://www.jiuzhang.com/solution/backpack/

猜你喜欢

转载自blog.csdn.net/yong_zi/article/details/81604049
今日推荐