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

禁忌搜索算法是一种优化算法,用于解决NP难问题,如0/1背包问题。下面是禁忌搜索算法0/1背包问题Python实现思路: 1. 随机生成一个初始解,即随机选择一些物品放入背包中。 2. 根据初始解,计算出初始解的价值。 3. 设定一个禁忌表,用于记录已经搜索过的解,以避免重复搜索。 4. 对于每个搜索步骤,根据当前解,生成一组邻居解。邻居解可以通过交换两个物品的位置或添加或删除一个物品来得到。 5. 对于每个邻居解,计算其价值,并判断其是否在禁忌表中。如果未在禁忌表中,则将其加入候选解集合中。 6. 从候选解集合中选择一个最优解作为下一次搜索的解,并将其加入禁忌表中。 7. 重复步骤4-6,直到达到停止条件。 8. 返回最优解。 下面是一个示例代码: ```python import random # 物品重量和价值 weights = [2, 3, 4, 5, 9] values = [3, 4, 5, 8, 10] # 背包容量和禁忌表大小 capacity = 20 tabu_size = 5 # 生成初始解 def generate_initial_solution(): solution = [] while sum(solution) < capacity: item = random.randint(0, len(weights) - 1) if weights[item] + sum(solution) <= capacity: solution.append(item) return solution # 计算解的价值 def evaluate_solution(solution): value = 0 for item in solution: value += values[item] return value # 生成邻居解 def generate_neighbors(solution): neighbors = [] for i in range(len(solution)): for j in range(i + 1, len(solution)): neighbor = solution.copy() neighbor[i], neighbor[j] = neighbor[j], neighbor[i] neighbors.append(neighbor) for i in range(len(solution)): neighbor = solution.copy() neighbor.pop(i) neighbors.append(neighbor) for j in range(len(weights)): if j not in neighbor and weights[j] + sum(neighbor) <= capacity: neighbor.append(j) neighbors.append(neighbor) return neighbors # 禁忌搜索算法 def taboo_search(): tabu_list = [] current_solution = generate_initial_solution() current_value = evaluate_solution(current_solution) best_solution = current_solution best_value = current_value while len(tabu_list) < tabu_size: tabu_list.append(current_solution) while True: neighbors = generate_neighbors(current_solution) candidate_solutions = [] for neighbor in neighbors: if neighbor not in tabu_list: candidate_solutions.append(neighbor) if not candidate_solutions: break candidate_values = [evaluate_solution(solution) for solution in candidate_solutions] best_candidate_value = max(candidate_values) best_candidate_index = candidate_values.index(best_candidate_value) best_candidate_solution = candidate_solutions[best_candidate_index] if best_candidate_value > best_value: best_solution = best_candidate_solution best_value = best_candidate_value current_solution = best_candidate_solution current_value = best_candidate_value tabu_list.pop(0) tabu_list.append(current_solution) return best_solution, best_value # 测试 best_solution, best_value = taboo_search() print('最优解:', best_solution) print('最优解的价值:', best_value) ``` 这段代码实现了禁忌搜索算法解决0/1背包问题的过程。在代码中,我们先定义了物品的重量和价值,背包的容量以及禁忌表的大小。然后,我们生成初始解并计算其价值。接着,我们在循环中不断生成邻居解,并计算其价值。如果邻居解不在禁忌表中,则将其加入候选解集合中。从候选解集合中选择一个最优解作为下一次搜索的解,并将其加入禁忌表中。最后,返回最优解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值