美文网首页动态规划
8. DP_01背包问题整理

8. DP_01背包问题整理

作者: Arthur_7724 | 来源:发表于2018-06-11 10:17 被阅读0次

    1.1 题目

    Given n items with size A[i], an integer m denotes the size of a backpack. How full you can fill this backpack?
    NoteYou
    can not divide any item into small pieces
    .Example
    If we have 4 items with size [2, 3, 5, 7], the backpack size is 11, we can select 2, 3 and 5, so that the max size we can fill this backpack is 10.
    If the backpack size is 12. we can select [2, 3, 7] so that we can fulfill the backpack.
    You function should return the max size we can fill in the given backpack.

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

    1.2 解题思路

    本题是典型的01背包问题,每种类型的物品最多只能选择一件。
    State:dp[i][S]表示前i个物品,取出一些能否组成和为S体积的背包
    Function:f[i][S] = f[i-1][S - A[i]] or f[i-1][S] (A[i]表示第i个物品的大小)
    转移方程想得到f[i][S]前i个物品取出一些物品想组成S体积的背包。 那么可以从两个状态转换得到。
    (1)f[i-1][S - A[i]] 放入第i个物品,并且前i-1个物品能否取出一些组成和为S-A[i] 体积大小的背包。
    (2)f[i-1][S]不放入第i个物品, 并且前i-1个物品能否取出一些组成和为S 体积大小的背包。
    Intialize:f[1…n][0] = true; f[0][1... m]= false
    初始化f[1...n][0]表示前1...n个物品,取出一些能否组成和为0 大小的背包始终为真。
    其他初始化为假
    Answer: 寻找使f[n][S]值为true的最大的S. (S的取值范围1到m)

    1.3 解题代码

    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 = 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--) {
              for (int j = A.length;j>=0;j--){
                  if (f[j][i]) {
                    return i;
                }
              }
            }
    
            return 0;
        }
    }
    

    2.1 题目

    Given n items with size A[i] and value V[i], and a backpack with size m. What's the maximum value can you put into the backpack?
    Note
    You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m.
    Example
    Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10.
    The maximum value is 9.

    两个数组,一个表示体积,另一个表示价值,给定一个容积为m的背包,求背包装入物品的最大价值。

    2.2 解题思路

    首先定义状态 K(i,w) 为 在面对第 i 件物品,且背包容量为 w 时所能获得的最大价值 ,则相应的状态转移方程为: K(i,w)=max{K(i−1,w),K(i−1,w−wi)+vi}

    2.3 解题代码

    public class Solution {
        /**
         * @param m: An integer m denotes the size of a backpack
         * @param A & V: Given n items with size A[i] and value V[i]
         * @return: The maximum value
         */
    
        public int backPackII(int m, int[] A, int V[]) {
            // write your code here
            int[][] dp = new int[A.length + 1][m + 1];
            for(int i = 0; i <= A.length; i++){
                for(int j = 0; j <= m; j++){
                    if(i == 0 || j == 0){
                        dp[i][j] = 0;
                    }
                    else if(A[i] > j){//已经装不下A[i]
                        dp[i][j] = dp[(i-1)][j];
                    }
                    else{
                        dp[i][j] = Math.max(dp[(i-1)][j], dp[(i-1)][j-A[i-1]] + V[i-1]);
                    }
                }
            }
            return dp[A.length][m];
        }
    }
    

    3.1 题目

    Given n kind of items with size Ai and value Vi( each item has an infinite number available) and a backpack with size m. What's the maximum value can you put into the backpack?
    Notice
    You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m.
    Example
    Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 15.

    这道题相比上题变为:重复选择+最大价值。

    3.2 解题思路

    和01背包问题很类似
    状态转移方程
    不放A[i]
    f[i][j] =f[i-1][j]
    放A[j]
    可放多个设为k,
    k = j/A[i]
    f[i][j] = f[i-1][j- kiA[i]] + kiA[i] 0<=ki<=k 取最大值 0<=ki*A[i]<=m

    3.3 解题代码

    public class Solution {
        /**
         * 多重背包问题
         * 总体积是m,每个小物品的体积是A[i]
         * 
         * @param m: An integer m denotes the size of a backpack
         * @param A: Given n items with size A[i] 0 开始的 A是
         * @return: The maximum size
         */
        public int backPackIII(int m, int[] A) {
            // write your code here
            int[][] P = new int[A.length+1][m+1];// P[i][j] 前i个物品放在j的空间中的最大价值
            for(int i = 0;i< A.length; i++){
                for(int j = m;j>=1;j--){
                    if(j>=A[i]){
                        int k = j/A[i];// 该物品最大可以放k个
                        while(k>=0){
                            if(j>=A[i]*k){
                                P[i+1][j] =Math.max(P[i+1][j], P[i][j-k*A[i]] + k*A[i]);
                            }
                            k--;
                        }
                    }
    
                    else
                        P[i+1][j] = Math.max(P[i][j],P[i+1][j]);
                }
            }
            return P[A.length][m];
        }
    }
    

    下一篇: 9. DP_leetcode 221 Maximal Square
    上一篇: 7. DP_leetcode 5 Longest Palindromic Substring最长回文子串

    相关文章

      网友评论

        本文标题:8. DP_01背包问题整理

        本文链接:https://www.haomeiwen.com/subject/yxwqeftx.html