[DnA] dp问题(野营)

描述:

假设你去野营。有一个重量为6(limit = 6)的背包,需要决定该携带某些东西,这些东西都有自己的重量和价值,如何选择能保证携带的东西具有最大价值?

水(sublimit:3,value:10)

书(sublimit:1,value:3)

食物(sublimit:2,value:9)

夹克(sublimit:2,value:5)

相机(sublimit:1,value:6)

解题思路:

所有dp问题都可以用 n*m 的二维矩阵解决,从左上角开始,按照从左往右,从上往下的顺序,依

次填充矩阵,填满以后便可看出来答案。

每个单元格求值公式:

matrix[i][j] = max(matrix[i - 1][j], value[i] + matrix[i - 1][j - 当前物品的限制])

此公式中 i j 的值依赖其上一行内元素的值,因此永远是有解的。

方案一 :

把限制条件也纳入矩阵,这个dp方法是通用方法,但是代码复杂,对关键策略的描述不清晰,建议使用方案二

matrix = []
sublimits = 0
limits = []
values = []


def makematrix():
    global limits
    limits = [int(x) for x in input().strip().split()]
    global sublimits
    sublimits = [int(x) for x in input().strip().split()]
    global values
    values = [int(x) for x in input().strip().split()]

    # 构建第一行
    line = []
    for j in range(0, len(limits) + 1):
        line.append(j)
    matrix.append(line)

    # 构建其他行
    for i in range(0, len(sublimits)):
        newline = [0 for k in range(0, len(limits) + 1)]
        newline[0] = sublimits[i]
        matrix.append(newline)


def dp(row, col):
    first = 0
    second = 0

    if row < 1 or col < 1:
        return 0

    # 矩阵位于自己上面的那个节点
    if row == 1:
        first = 0
    else:
        first = matrix[row - 1][col]  # 矩阵位于自己上面的那个节点

    if sublimits[row - 1] > limits[col - 1]:  # 如果自身的限制大于当前列的限制,则为0
        second = 0
    else:
        if row == 1:
            second = values[row - 1]  # 如果是第一行,那么上一行是不存在的,又因为已经满足了自身限制小于总限制,所以就以自己的当前价值作为本节点的值
        else:
            if col == 1:
                second = values[row - 1]  # 当前的分数 + 在上一行(ROW-1)中找总限制减去当前限制(limits[col-1]-sublimits[row-1])后的值
            else:
                second = values[row - 1] + matrix[row - 1][limits[col - 1] - sublimits[row - 1]]  # 当前的分数 + 在上一行(ROW-1)中找总限制减去当前限制(limits[col-1]-sublimits[row-1])后的值

    matrix[row][col] = max(first, second)
    print(matrix[row][col])


makematrix()
# 单元格遍历顺序是 按行遍历
for row in range(1, len(sublimits) + 1):
    for col in range(1, len(limits) + 1):
        dp(row, col)

方案二:

matrix = []
sublimits = 0
limits = []
values = []


def makematrix():
    global limits
    limits = [int(x) for x in input().strip().split()]
    global sublimits
    sublimits = [int(x) for x in input().strip().split()]
    global values
    values = [int(x) for x in input().strip().split()]

    # 构建矩阵
    for i in range(0, len(sublimits)):  #共sublimits行
        newline = [0 for k in range(0, len(limits))]    #每行limits列
        matrix.append(newline)

    # 构建第一行
    for j,ele in enumerate(limits):
        if  ele >= sublimits[0]:
            matrix[0][j] = values[0]
        else:
            matrix[0][j] = 0

    first = 0
    second = 0
    # 构建第一列
    for k in range(1,len(sublimits)):   #第一列的第一行已经在构建第一行时构建好了
        first = matrix[k-1][0]

        if limits[0]>=sublimits[k]:
            second = values[k]
        else:
            second = 0

        matrix[k][0] = max(first,second)

def dp(row, col):
    first = 0
    second = 0

    if row < 1 or col < 1:
        return 0

    # 矩阵位于自己上面的那个节点
    first = matrix[row - 1][col]  # 矩阵位于自己上面的那个节点

    # 如果自身的限制大于当前列的限制,则为0
    if sublimits[row - 1] > limits[col - 1]:
        second = 0
    # 否则为当前的分数 + 在上一行(ROW-1)中找总限制减去当前限制(limits[col-1]-sublimits[row-1])后的值
    else:
        # 找到 总限制减去当前限制 得到的 限制值在表中的哪一列
        ind = 0
        for index,ele in enumerate(limits):
            if ele == limits[col] - sublimits[row]:
                ind = index

        second = values[row] + matrix[row - 1][ind]  # 当前的分数 + 在上一行(ROW-1)中找总限制减去当前限制(limits[col-1]-sublimits[row-1])后的值

    matrix[row][col] = max(first, second)


makematrix()
# 单元格遍历顺序是 按行遍历
for row in range(1, len(sublimits)):
    for col in range(1, len(limits)):
        dp(row, col)
print(matrix)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值