python算法0/1背包问题

一维数组循环

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
https://zhuanlan.zhihu.com/p/78060568
1) input:
4 5   物品总数  不超过总重量
1 2   重量  价值
2 4
3 4
4 5
output:
8

https://en.wikipedia.org/wiki/Knapsack_problem
2) input:
10 67
23 505
26 352
20 458
18 220
32 354
27 414
29 498
26 545
30 473
27 543
output:
1270
"""
# 01背包问题 利用一维数组进行
a = raw_input()
n, m = list(map(int, a.split()))
w = [0 for i in range(n + 1)]
v = [0 for i in range(n + 1)]
for i in range(1, n + 1):
    b = raw_input()
    w[i], v[i] = list(map(int, b.split()))

# 定义一个数组 f[j] 表示容量为j的情况下能放的总价值最大
f = [0 for i in range(m + 1)]
# print(f)
for i in range(1, n + 1):
    for j in range(m, 0, -1):  # 容量从大到小遍历
        if j >= w[i]:
            f[j] = max(f[j], f[j - w[i]] + v[i])
        else:
            break
# j为容量不断上升 当容量大于当前的时候才可以放下这个
print(f[-1])

递归计算

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
https://en.wikipedia.org/wiki/Knapsack_problem
input:
10 67
23 505
26 352
20 458
18 220
32 354
27 414
29 498
26 545
30 473
27 543
output:
1270
"""
a = raw_input()
n, W = list(map(int, a.split()))
w = [0 for i in range(n + 1)]
v = [0 for i in range(n + 1)]
for i in range(1, n + 1):
    b = raw_input()
    w[i], v[i] = list(map(int, b.split()))
# 二维数组暂存,一维是物品数个list,每个list里是重量0到最大个值,表示前i个物品在重量限制值时的最大值
value = [[-1 for i in range(W + 1)] for j in range(n + 1)]


def max_value(i, j):
    """
    Define function m so that it represents the maximum value we can get under the condition:
    use first i items, total weight limit is j

    :param i:  物品数量
    :param j:  最大重量值
    :return:   达到最大重量值时,最大价值
    """
    if i <= 0 or j <= 0:
        value[i][j] = 0
        return 0
    # has not been calculated, we have to call function
    if value[i - 1][j] == -1:
        value[i - 1][j] = max_value(i - 1, j)
    # item cannot fit in the bag
    if w[i] > j:
        value[i][j] = value[i-1][j]
    else:
        # value[i-1][j-w[i]] has not been calculated, we have to call function
        if value[i-1][j-w[i]] == -1:
            value[i - 1][j - w[i]] = max_value(i-1, j-w[i])
        # 包可以容纳下当前第i个物品,这样,前i个物品在重量限制j时的最大价值为
        # 就是比较下面,取最大值
        # 1. 前i-1个物品满载,达到包容量时的最大价值
        # 2. 前i-1个物品,且重量刚好可以容纳第i个物品而没有容纳时,的最大价值加上此时第i个物品的价值之和
        value[i][j] = max(value[i-1][j], value[i-1][j-w[i]]+v[i])
    return value[i][j]


print max_value(n, W)
print value

使用dict优化上面递归时的数组存储

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
https://en.wikipedia.org/wiki/Knapsack_problem
input:
10 67
23 505
26 352
20 458
18 220
32 354
27 414
29 498
26 545
30 473
27 543
output:
1270
"""
a = raw_input()
n, W = list(map(int, a.split()))
w = [0 for i in range(n + 1)]
v = [0 for i in range(n + 1)]
for i in range(1, n + 1):
    b = raw_input()
    w[i], v[i] = list(map(int, b.split()))
value = {}


def get_value(a, b):
    if value.get(a) is None:
        return -1
    if value.get(a).get(b) is None:
        return -1
    # print "get %s,%s val %s" % (a, b, value.get(a).get(b))
    return value.get(a).get(b)


def set_value(a, b, val):
    if value.get(a) is None:
        value[a] = {}
    # print "set %s,%s to %s" % (a, b, val)
    value.get(a)[b] = val


def max_value(i, j):
    """
    Define function m so that it represents the maximum value we can get under the condition:
    use first i items, total weight limit is j

    :param i:  物品数量
    :param j:  最大重量值
    :return:   达到最大重量值时,最大价值
    """
    if i <= 0 or j <= 0:
        set_value(i, j, 0)
        return 0
    # has not been calculated, we have to call function
    if get_value(i-1, j) == -1:
        set_value(i-1, j, max_value(i-1, j))
    # item cannot fit in the bag
    if w[i] > j:
        set_value(i, j, get_value(i-1, j))
    else:
        # value[i-1][j-w[i]] has not been calculated, we have to call function
        if get_value(i-1, j-w[i]) == -1:
            set_value(i-1, j-w[i], max_value(i-1, j-w[i]))
        # 包可以容纳下当前第i个物品,这样,前i个物品在重量限制j时的最大价值为
        # 就是比较下面,取最大值
        # 1. 前i-1个物品满载,达到包容量时的最大价值
        # 2. 前i-1个物品,且重量刚好可以容纳第i个物品而没有容纳时,的最大价值加上此时第i个物品的价值之和
        set_value(i, j, max(get_value(i-1, j), get_value(i-1, j-w[i])+v[i]))

    # print "%s,%s max return %s" % (i, j, get_value(i, j))
    return get_value(i, j)


print max_value(n, W)
print value

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值