背包型动态规划

Posted lizzyluvcoding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了背包型动态规划相关的知识,希望对你有一定的参考价值。

92. Backpack

可行性

https://www.lintcode.com/problem/backpack/description?_from=ladder&&fromId=16

技术图片
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) {
        // write your code here
        int n = A.length;
        if(n==0){
            return 0;
        }
        //前i个物品拼出j的重量
        boolean[][] f = new boolean[n+1][m+1];
        
        for(int i =1;i<=m;i++){
            f[0][i]= false;
        }
        
        f[0][0]= true;
        for(int i=1;i<=n;i++){
            for(int w =0;w<=m;w++){
                f[i][w] = f[i-1][w];
                
                if(w>=A[i-1]){
                    f[i][w]=(f[i][w] || f[i-1][w-A[i-1]]);
                }
            }
        }
        
        for(int i = m;i>=0;i--){
            if(f[n][i]){
                return i;
            }
        }
        
        return 0;
    }
}
View Code

滚动数组优化版:

技术图片
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) {
        // write your code here
        int n = A.length;
        if(n==0){
            return 0;
        }
        //前i个物品拼出j的重量
        boolean[][] f = new boolean[n+1][m+1];
        
        int old =0;
        int now =0;
        
        for(int i =1;i<=m;i++){
            f[now][i]= false;
        }
        
        f[now][0]= true;
        for(int i=1;i<=n;i++){
            old = now;
            now = 1-now;
            for(int w =0;w<=m;w++){
                f[now][w] = f[old][w];
                
                if(w>=A[i-1]){
                    f[now][w]=(f[now][w] || f[old][w-A[i-1]]);
                }
            }
        }
        
        for(int i = m;i>=0;i--){
            if(f[now][i]){
                return i;
            }
        }
        
        return 0;
    }
}
View Code

 

正整数求和可考虑背包问题

563. Backpack V

计数型

https://www.lintcode.com/problem/backpack-v/?_from=ladder&&fromId=16

技术图片
public class Solution {
    /**
     * @param nums: an integer array and all positive numbers
     * @param target: An integer
     * @return: An integer
     */
    //f[i][w] = f[i-1][w]+f[i-1][w-A[j]]
    //初始条件:f[0][0] = 1
    // f[0][1...m] = 0;
    public int backPackV(int[] nums, int target) {
        // write your code here
        if(nums==null || nums.length==0){
            return 0;
        }
        int n = nums.length;
        
        int[][] f = new int[n+1][target+1];
        
        for(int i=1;i<=target;i++){
            f[0][i] =0;
        }
        
        f[0][0] = 1;
        
        for(int i =1;i<=n;i++){
            for(int w =0;w<=target;w++){
                f[i][w]= f[i-1][w];
                if(w>=nums[i-1]){
                    f[i][w]+=f[i-1][w-nums[i-1]];
                }
            }
        }
        
        return f[n][target];
        
    }
}
View Code

空间优化成一维滚动数组

技术图片
public class Solution {
    /**
     * @param nums: an integer array and all positive numbers
     * @param target: An integer
     * @return: An integer
     */
    //f[i][w] = f[i-1][w]+f[i-1][w-A[j]]
    //初始条件:f[0][0] = 1
    // f[0][1...m] = 0;
    public int backPackV(int[] nums, int target) {
        // write your code here
        if(nums==null || nums.length==0){
            return 0;
        }
        int n = nums.length;
        
        int[] f = new int[target+1];
        
        for(int i=1;i<=target;i++){
            f[i] =0;
        }
        
        f[0] = 1;
        
        for(int i =1;i<=n;i++){
            //right -> left
            for(int w =target;w>=nums[i-1];w--){
                    f[w]+=f[w-nums[i-1]]; //overwrit
                
            }
        }
        
        return f[target];
        
    }
}
View Code

 

564. Combination Sum IV

计数型

https://www.lintcode.com/problem/combination-sum-iv/description?_from=ladder&&fromId=16

技术图片
public class Solution {
    /**
     * @param nums: an integer array and all positive numbers, no duplicates
     * @param target: An integer
     * @return: An integer
     */
    public int backPackVI(int[] nums, int target) {
        // write your code here
        if(nums==null || nums.length==0){
            return 0;
        }
        
        if(target==0){
            return 0;
        }
        
        int[] f = new int[target+1];
        f[0]=1;
        
        for(int i =1;i<=target;i++){
            for(int j=0;j<nums.length;j++){
                if(i>=nums[j])
                    f[i]+=f[i-nums[j]];
            }
        }
        
        return f[target];
        
    }
}
View Code

 

125. Backpack II

最值型

https://www.lintcode.com/problem/backpack-ii/description?_from=ladder&&fromId=16

技术图片
public class Solution {
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @param V: Given n items with value V[i]
     * @return: The maximum value
     */
    public int backPackII(int m, int[] A, int[] V) {
        // write your code here
        if(A==null || A.length==0 || V==null || V.length ==0){
            return 0;
        }
        
        int n = A.length;
        
        int[][] f = new int[n+1][m+1];
        f[0][0] = 0;
        
        for(int i =1;i<=m;i++){
            f[0][i] = -1;
        }
        
        for(int i=1;i<=n;i++){
            for(int w=0;w<=m;w++){
                f[i][w] = f[i-1][w];
                if(w>=A[i-1] && f[i-1][w-A[i-1]]!=-1){
                    f[i][w] = Math.max(f[i][w],f[i-1][w-A[i-1]]+V[i-1]);
                }
            }
        }
        
        int res = 0;
        for(int i =0;i<=m;i++){
            res = Math.max(res,f[n][i]);
        }
        
        return res;
    }
}
View Code

 

440. Backpack III

最值型

https://www.lintcode.com/problem/backpack-iii/description?_from=ladder&&fromId=16

思路:由Backpack II扩展出来,设k为i-1物体取用次数

技术图片
public class Solution {
    /**
     * @param A: an integer array
     * @param V: an integer array
     * @param m: An integer
     * @return: an array
     */
    public int backPackIII(int[] A, int[] V, int m) {
        // write your code here
        if(A==null || A.length==0 || V==null || V.length==0){
            return 0;
        }
        
        int n = A.length;
        
        int[][]f = new int[n+1][m+1];
        
        f[0][0] = 0;
        
        for(int i=1;i<=m;i++){
            f[0][i]=-1;
        }
        
        for(int i=1;i<=n;i++){
            for(int w=0;w<=m;w++){
                f[i][w] = f[i-1][w];
                int currW = w;
                int k =1;
                while(currW>=A[i-1]){
                    if(f[i-1][currW-A[i-1]]!=-1){
                        f[i][w] = Math.max(f[i][w],f[i-1][currW-A[i-1]]+V[i-1]*k);
                    }
                    currW-=A[i-1];
                    k++;
                }
            }
        }
        
        int res = 0;
        for(int i=1;i<=m;i++){
            res = Math.max(res,f[n][i]);
        }
        
        return res;
    }
}
View Code

 

优化1:观察公式,进行简化

优化思路,其实最后一个无论取几次,都相当于k-1次取值f[i][w-A[i-1]]+V[i-1];

技术图片
public class Solution {
    /**
     * @param A: an integer array
     * @param V: an integer array
     * @param m: An integer
     * @return: an array
     */
    public int backPackIII(int[] A, int[] V, int m) {
        // write your code here
        if(A==null || A.length==0 || V==null || V.length==0){
            return 0;
        }
        
        int n = A.length;
        
        int[][]f = new int[n+1][m+1];
        
        f[0][0] = 0;
        
        for(int i=1;i<=m;i++){
            f[0][i]=-1;
        }
        
        for(int i=1;i<=n;i++){
            for(int w=0;w<=m;w++){
                f[i][w] = f[i-1][w];
                //优化思路,其实最后一个无论取几次,都相当于k-1次取值f[i][w-A[i-1]]+V[i-1];
                if(w>=A[i-1] && f[i][w-A[i-1]]!=-1){
                    f[i][w] = Math.max(f[i][w],f[i][w-A[i-1]]+V[i-1]);
                }
            }
        }
        
        int res = 0;
        for(int i=1;i<=m;i++){
            res = Math.max(res,f[n][i]);
        }
        
        return res;
    }
}
View Code

 

优化2:画图之后改成一维滚动数组

技术图片
public class Solution {
    /**
     * @param A: an integer array
     * @param V: an integer array
     * @param m: An integer
     * @return: an array
     */
    public int backPackIII(int[] A, int[] V, int m) {
        // write your code here
        if(A==null || A.length==0 || V==null || V.length==0){
            return 0;
        }
        
        int n = A.length;
        
        int[]f = new int[m+1];
        
        f[0] = 0;
        
        for(int i=1;i<=m;i++){
            f[i]=-1;
        }
        
        for(int i=1;i<=n;i++){
            for(int w=0;w<=m;w++){
                //优化思路,其实最后一个无论取几次,都相当于k-1次取值f[i][w-A[i-1]]+V[i-1];
                if(w>=A[i-1] && f[w-A[i-1]]!=-1){
                    f[w] = Math.max(f[w],f[w-A[i-1]]+V[i-1]);
                }
            }
        }
        
        int res = 0;
        for(int i=1;i<=m;i++){
            res = Math.max(res,f[i]);
        }
        
        return res;
    }
}
View Code

 

以上是关于背包型动态规划的主要内容,如果未能解决你的问题,请参考以下文章

背包型动态规划

背包型动态规划

noip(提高组难度)动态规划有哪几种类型?(如:坐标DP、背包DP等) 各都有哪些经典题目?

动态规划_01背包_完全背包_多重背包_分组背包

动态规划-第二节:动态规划之背包类型问题

分别用回溯法和动态规划求0/1背包问题(C语言代码)