【剑指offer】背包

1、0-1背包

有一个容量为 j 的背包,要用这个背包装下物品的价值最大,这些物品有两个属性:体积 w 和价值 v。

一件物品有两种情况:装 or 不装;每个物品只能装一件;

对于物品 i,体积为 wi,价值为 vi:

(1)i 的体积 > 背包的体积,不装,此时背包的最大价值为不装 i 的价值 :

        dp[i][j] = dp[i-1][j]

(1)i 的体积 < 背包的体积,可以装 也可以 不装,不装,同(1);装,则等同于将前 i-1 个物品装进剩余容量 j-w 的背包中,再加上物品 i 的价值,取两种可能的最大值,装了价值肯定最大:

       dp[i][j] = max(dp[i-1][j] ,dp[i-1][j-w] + v)

def knapsack(W,N,weights,values):
    dp = [[0 for i in range(W+1)] for j in range(N+1)]
    for i in range(1,N+1):
        w = weights[i-1]
        v = values[i-1]
        for j in range(W,0,-1):
            if j >= w:
                dp[i][j] = max(dp[i-1][j],dp[i-1][j-w]+v)
            else:
                dp[i][j] = dp[i-1][j]
    print( dp[N][W]) # 11

W = 10
N = 3
weights = [3,4,5]
values = [4,5,6]
knapsack( W,N ,weights,values)

2、完全背包

'''完全背包'''
def CompletePack(N, V, weight, value):
    """
    完全背包问题(每个物品可以取无限次)
    :param N: 物品个数, 如 N=5
    :param V: 背包总容量, 如V=15
    :param weight: 每个物品的容量数组表示, 如weight=[5,4,7,2,6]
    :param value: 每个物品的价值数组表示, 如value=[12,3,10,3,6]
    :return: 返回最大的总价值
    """
    # 初始化f[N+1][V+1]为0,f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值
    f = [[0 for col in range(N + 1)] for row in range(V + 1)]

    for i in range(1, V+1):
        for j in range(1, N+1):
            # 注意由于weight、value数组下标从0开始,第i个物品的容量为weight[i-1],价值为value[i-1]
            # V/weight[i-1]表示物品i最多可以取多少次
            f[i][j] = f[i - 1][j]  # 初始取k=0为最大,下面的循环是把取了k个物品i能获得的最大价值赋值给f[i][j]
            nCount  = j//weight[i-1]+1
            for k in range(nCount):
                if f[i][j] < f[i-1][j-k*weight[i-1]]+k*value[i-1]:
                    f[i][j] = f[i-1][j-k*weight[i-1]]+k*value[i-1]  # 状态方程

            # 上面的f[i][j]也可以通过下面一行代码求得
            #  f[i][j] = max([f[i-1][j-k*weight[i-1]]+k*value[i-1] for k in range(j/weight[i-1]+1)])
    max_value = f[V][N]
    print(max_value)
    return max_value

W = 10
N = 3
weights = [3,4,5]
values = [4,5,6]
CompletePack(W,N ,weights,values) #13

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值