背包问题

背包问题

有n件物品和容量为m的背包 给出i件物品的重量以及价值,
求解让装入背包的物品重量不超过背包容量且价值最大 。
一个讲解很好的博客。看了之后可以理解如何得到背包问题的状态转移方程。

1. 0/1背包问题

特点:每种物品只有一件,供你选择放与不放。

def Bag01(n, weights, values, cap):
    dplist = [[0 for j in range(cap+1)] for i in range(n)]
    for i in range(cap+1):
        if weights[0] <= i:
            dplist[0][i] = values[0]
    for i in range(1, n):
        for j in range(cap+1):
            if weights[i] <= j:
                dplist[i][j] = max(dplist[i-1][j], values[i] + dplist[i-1][j-weights[i]])
            else:
                dplist[i][j] = dplist[i-1][j]
    return dplist[n-1][cap]

空间复杂度O(n*cap),可以观察出dplist的第i行只和第i-1行有关,所以可以简化为一维数组。

for i in range(1, n):
    for j in range(cap, -1, -1):
        if weights[i] <= j:
            dplist[j] = max(dplist[j], values[i] + dplist[j-weights[i]])

2. 完全背包问题

特点:物品不再只有一个,可以无限复用。

def Bag3(n, weights, values, cap):
    dplist = [[0 for i in range(cap+1)] for j in range(n)]
    for i in range(1, cap+1):
        num = i // weights[0]
        dplist[0][i] = num*values[0]
    for i in range(1, n):
        for j in range(1, cap+1):
            if weights[i] <= j:
                num = j // weights[i]
                dplist[i][j] = max(dplist[i-1][j], dplist[i-1][j-num*weights[i]] + values[i]*num)
            else:
                dplist[i][j] = dplist[i-1][j]
    return dplist[n-1][cap]

一维数组

for i in range(1, n):
	for j in range(cap, -1, -1):
	    if weights[i] <= j:
	        num = j // weights[i]
	        dplist[j] = max(dplist[j], dplist[j-num*weights[i]] + values[i]*num)

3. 多重背包问题

特点:物品不再可以无限复用,而是有数量限制。

def Bag4(n, weights, values, nums, cap):
    dplist = [[0 for i in range(cap+1)] for j in range(n)]
    for i in range(1, cap+1):
        num = i // weights[0]
        if num <= nums[0]:
            dplist[0][i] = num*values[0]
        else:
            dplist[0][i] = nums[0]*values[0]
    for i in range(1, n):
        for j in range(1, cap+1):
            if weight[i] <= j:
                num = j // weights[0]
                if num <= nums[0]:
                    dplist[i][j] = max(dplist[i - 1][j], dplist[i - 1][j - num * weights[i]] + values[i] * num)
                else:
                    dplist[i][j] = max(dplist[i - 1][j], dplist[i - 1][j - nums[i] * weights[i]] + values[i] * nums[i])
			else:
				dplist[i][j] = dplist[i-1][j]
    return dplist[n-1][cap]

一维数组

for i in range(1, n):
    for j in range(cap, -1, -1):
        if weight[i] <= j:
            num = j // weights[0]
            if num <= nums[0]:
                dplist[j] = max(dplist[j], dplist[j - num * weights[i]] + values[i] * num)
            else:
                dplist[j] = max(dplist[j], dplist[j - nums[i] * weights[i]] + values[i] * nums[i])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值