【算法】动态规划

0-1背包问题

"""
动态规划问题
基本思想:参考合并排序算法
分而治之理念
"""


"""
功能描述:自定义背包函数,实现动态规划算法
参数说明:count:表示物品件数
        TotalWeight:表示背包的总容量
        weight:表示每件物品的重量
        cost:表示每件物品的价值
"""
import numpy as np

# 用常规方案实现功能
def bag(count, TotalWeight, weight, cost):
    # value = [[0 for j in range(TotalWeight + 1)] for i in range(count + 1)]  # 置零,表示初始状态
    value = np.array([[0] * (TotalWeight + 1)] * (count + 1))                  # numpy 实现
    # print(value)

    for i in range(1, count+1):                                                # 遍历物品件数,从第1件物品计算
        for j in range(1, TotalWeight + 1):                                    # 遍历背包容纳量,从重量为1开始计算
            value[i][j] = value[i - 1][j]                                      # 定义value数组存储最大价值
            print(value)
                                                                               # 背包总容量够放当前物体,遍历前一个状态考虑是否置换
            if j >= weight[i - 1] and value[i][j] < value[i - 1][j - weight[i - 1]] + cost[i - 1]:
                value[i][j] = value[i - 1][j - weight[i - 1]] +cost[i - 1]     # 最大价值就是 当前物品的价值+剩余空间的价值
    return value                                                               # 返回最大价值

# 用numpy实现如上功能
def fun(n, W, w, p):
    a = np.array([[0] * (W + 1)] * (n + 1))

    # 依次计算前i个行李的最大价值,n+1在n的基础上进行
    for i in range(1, n + 1):
        for j in range(1, W + 1):
            if w[i - 1] > j:
                a[i][j] = a[i - 1][j]
            else:
                a[i, j] = max(a[i - 1, j], p[i - 1] + a[i - 1, j - w[i - 1]])  # 2种情况取最大值

    findDetail(p, n, a[n, W])

# 找到价值列表中的一个子集,使得其和等于前面求出的最大价值,即为选择方案
def findDetail(p, n, v):
    a = np.array([[True] * (v + 1)] * (n + 1))
    for i in range(0, n + 1):
        a[i][0] = True
    for i in range(1, v + 1):
        a[0][i] = False
    for i in range(1, n + 1):
        for j in range(1, v + 1):
            if p[i - 1] > j:
                a[i, j] = a[i - 1, j]
            else:
                a[i, j] = a[i - 1, j] or a[i - 1, j - p[i - 1]]
    if a[n, v]:
        i = n
        result = []
        while i >= 0:
            if a[i, v] and not a[i - 1, v]:
                result.append(p[i - 1])
                v -= p[i - 1]
            if v == 0:
                break
            i -= 1
        print(result)
    else:
        print('error')

"""
功能:自定义显示输出结果函数
参数说明:  count:表示物品件数
          TotalWeight:表示背包的总容量
          weight:表示每件物品的重量
          value:表示最大价值,即所求的结果
"""

def show(count, TotalWeight, weight, value):
    x = [False for i in range(count)]                        # 初始化x,使得x为假
    j = TotalWeight                                          # 背包的容量赋给变量j
    for i in range(count, 0, -1):                            # 遍历每个物品
        if value[i][j] > value[i - 1][j]:                    # 如果value[i][j]单元格大于上一行同列的单元格的价值,进行更新
            x[i - 1] = True
            j -= weight[i - 1]                               # 总容量减去上一行同列的单元格的重量
    print('最大价值为:', value[count][TotalWeight])            # 输出最大价值的值
    print('背包中所装物品为:')
    for i in range(count):                                   # 遍历物品数
        if x[i]:                                             # 判断最大价值的物品数
            print('第', i + 1, '个 ', end='')                 # 输出是第几个物品


count = 3                                                    # 一共有3件物品
TotalWeight = 4                                              # 背包的总容量是4
weight = [1, 4, 3]                                           # 每个物品的重量
cost = [4900, 7800, 5600]                                    # 每个物品的价值
value = bag(count, TotalWeight, weight, cost)                # 调用bag()函数动态规划算法函数
# show(count, TotalWeight, weight, value)                    # 调用show()函数输出结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凡先生的笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值