01背包

125. 背包问题 II

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

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

样例
样例 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) 空间复杂度吗?

注意事项
A[i], V[i], n, m 均为整数
你不能将物品进行切分
你所挑选的要装入背包的物品的总大小不能超过 m
每个物品只能取一次

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
    """
    def backPackII(self, m, A, V):
        # write your code here
        n = len(A)
        
        A = [0] + A #多加一个0,为了方便后续没有为i-1的操作
        V = [0] + V
        
        a = [[0 for _ in range(m+1)] for _ in range(n+1)] #n*m
        
        #前i个物品,放入容量为j的背包
        for i in range(1, n+1):
            for j in range(0, m+1):
                if j < A[i]:
                    #当前物品比背包容量还大,不放
                    a[i][j] = a[i-1][j]
                    continue
                '''
                不放第i件为a[i-1][j],背包容量为j,
                放第i件为a[i-1][j-A[i]],背包容量减少为j-A[i]
                注意都为a[i-1],因为a[i][j]表示前i件物品放入容量为j的
                背包,所产生的最大价值,要计算的是a[i][j],所以放第i件物品时其收益为之间的最大收益为a[i-1][j-A[i]],在加上当前的收益V[i]
                '''
                
                a[i][j] = max(a[i-1][j], a[i-1][j-A[i]] + V[i])
        
        return a[n][m]
                

92. 背包问题

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

样例
样例 1:
输入: [3,4,8,5], backpack size=10
输出: 9

样例 2:
输入: [2,3,5,7], backpack size=12
输出: 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.

注意事项
你不可以将物品进行切割。

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
    """
    def backPack(self, m, A):
        # write your code here
        n = len(A)
        A = [0]+ A
        
        a = [[0 for _ in range(m+1)] for _ in range(n+1)]
        
        for i in range(1,n+1):
            for j in range(1, m+1):
                if j < A[i]:
                    a[i][j] = a[i-1][j]
                    continue
                a[i][j] = max(a[i-1][j], a[i-1][j-A[i]] + A[i])
                
        return a[n][m]

563. 背包问题 V

给出 n 个物品, 以及一个数组, nums[i] 代表第i个物品的大小, 保证大小均为正数, 正整数 target 表示背包的大小, 找到能填满背包的方案数。
每一个物品只能使用一次

样例
给出候选物品集合 [1,2,3,3,7] 以及 target 7

结果的集合为:
[7]
[1,3,3]
返回 2

class Solution:
    """
    @param nums: an integer array and all positive numbers
    @param target: An integer
    @return: An integer
    a[i][j]前i个物品填满容量为j的背包的方案数
    a[i][j] = a[i-1][j] + a[i-1][j-nums[i]]
    注意初始化a[0][0]=1,前0个物品能填满容量为0的背包
    """
    def backPackV(self, nums, m):
        # write your code here
        n = len(nums)
        nums = [0]+ nums
        
        a = [[0 for _ in range(m+1)] for _ in range(n+1)]
        
        a[0][0] = 1
        
        for i in range(1, n+1):
            for j in range(0, m+1): #背包容量从0开始
				 #不放第i个物品
                if j < nums[i]:
                    a[i][j] = a[i-1][j]
                    continue
                
                '''
                a[i-1][j]不放第i个物品
                a[i-1][j-num[i]] 放第i个物品,相当于将前i-1个物品放入j-nums[i]的空间中去
                '''
                a[i][j] = a[i-1][j] + a[i-1][j-nums[i]]
                
        return a[n][m] 

java版

public class Solution {
    /**
     * @param nums: an integer array and all positive numbers
     * @param target: An integer
     * @return: An integer
     */
    public int backPackV(int[] nums, int target) {
        // write your code here
        int n = nums.length;
        int m = target;
        int i,j;
        
        int [][] a = new int[n+1][m+1];
        
        for(i=0; i < m+1; ++i){
            a[0][i] = 0;
        }
        a[0][0] = 1;
        
        for(i = 1; i < n+1; ++i){
            for(j=0;j< m+1; ++j){
                a[i][j] = a[i-1][j];
                
                if (j >= nums[i-1]){
                    a[i][j] += a[i-1][j-nums[i-1]];
                }
               
                
            }
        }
        return a[n][m];
    }
}

564. 组合总和 IV

给出一个都是正整数的数组 nums,其中没有重复的数。从中找出所有的和为 target 的组合个数。

样例
样例1

输入: nums = [1, 2, 4] 和 target = 4
输出: 6
解释:
可能的所有组合有:
[1, 1, 1, 1]
[1, 1, 2]
[1, 2, 1]
[2, 1, 1]
[2, 2]
[4]
样例2

输入: nums = [1, 2] 和 target = 4
输出: 5
解释:
可能的所有组合有:
[1, 1, 1, 1]
[1, 1, 2]
[1, 2, 1]
[2, 1, 1]
[2, 2]
注意事项
一个数可以在组合中出现多次。
数的顺序不同则会被认为是不同的组合。

class Solution:
    """
    @param nums: an integer array and all positive numbers, no duplicates
    @param target: An integer
    @return: An integer
    """
    '''
    注意到结果是无序的,故不能按照传统的背包方法设a[i][j]为前i种物品填满容量为j的背包的方案数,即完全背包的做法是行不通的,因为他有顺序性。
    本题设置a[i]表示有多少中组合能拼成重量i
    a[i] = a[i-A[0]] + a[i-A[1]]....+a[i-A[k-1]], i>=A[k-1]
    
    '''
    def backPackVI(self, nums, m):
        # write your code here
        n = len(nums)
        
        
        a = [0 for _ in range(m+1)]
        
        a[0] = 1
        
        for i in range(1, m+1):
            for j in range(n):
                if nums[j] <= i:
                    a[i] += a[i-nums[j]]
        
        return a[m]
       
        
        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值