0-1 背包

一.问题描述:
有 n 件物品 和 一个最多能背重量为 w 的背包。第 i 件物品的重量是weight[i],得到的价值是value[i]。每件物品只能用一次,求解将哪些物品装入背包物体的价值总和最大。
二.算法:
1).暴力思路:
        每一个物体只有两种状态(取,不取),n个物体的话就有2 ^ n种状态
2).动态规划:
        存放[0-i]的物体的背包容量为j的背包 使其存放物品的价值量最大的状态依赖 存放[0 - i-1]的物品的容量为j-1的背包 的状态相关
动态规划五部曲(来自--代码随想录):
1.确定dp数组含义:dp[i][j] -- 将[0,i]的物体放到容量为 j 的背包,所能达到的最大价值量

2.递推公式:dp[i][j] = 不放 i(需要判断先能不能放i) : dp[i-1][j] ; 放第 i 号物品 : dp[i-1][j-weight[i]] + value[i]

3.初始化:
dp[x][0] -- 第 0 列 表示将[0,x]的物体放到容量为 0 的背包,显然价值为 0 
dp[0][x] -- 第 1 行 表示将[0,0]的物体放到容量为 x 的背包,总价值 = if x >= weight[0]:dp[0][x] = value[0] else dp[0][x] = 0

4.遍历顺序:
先行后列 或 先列后行 均可(dp[i][j] 的值只与其上面 和 斜上角的值有关)

5.打印dp数组,debug
print(dp) 查看是否符合题目要求

三.代码 -- python        
# M = 6   # 物品种类 -- 每个物品只有一个
# K = 1   # 背包空间
# value = [2,3,1,5,4,3]   # 每个物品的价值
# weight = [2,2,3,1,5,2]  # 每个物品的重量
value = []
weight = []
# 接收外部传来的参数
# 第一行传入M , K
s1 = input("please input M and K,divide by ' ' ")
M = int(s1.split()[0])
K = int(s1.split()[1])
# 第二行传入weight列表
s2 = input("please input list of weight,divide by ' ' ")
s2_list = s2.split(" ")
for e in s2_list:
    weight.append(int(e))
# 第三行传入value列表
s3 = input("please input list of value,divide by ' ' ")
s3_list = s3.split(" ")
for e in s3_list:
    value.append(int(e))

# 背包的大小不能为 0 且 物品的种类不能为 0
if K <= 0 or M <= 0:
    print(f"背包的空间 为小于等于0的值;放不进去任何物品")

# 创建dp数组 -- 大小为 : M x (K + 1) ( M 是总物品的个数 [0 - M-1] , K 是背包的最大容量)
# dp[i][j] -- 将[0,i]的物体放到容量为 j 的背包,所能包含的最大价值量
dp = []
for i in range(M):
    dp.append([0] * (K + 1))

# 递推公式 -- dp[i][j] = 不放 i : dp[i-1][j] ; 放第 i 号物品 : dp[i-1][j-weight[i]] + value[i]
# dp[i][j] = max( dp[i-1][j] , dp[i-1][j-weight[i]] + value[i] )
# 初始化
# dp[x][0] -- 第 0 列 表示将[0,x]的物体放到容量为 0 的背包,显然价值为 0
# dp[0][x] -- 第 1 行 表示将[0,0]的物体放到容量为 x 的背包,总价值 = if x >= weight[0]:dp[0][x] = value[0] else dp[0][x] = 0
for i in range(M):
    dp[i][0] = 0
for i in range(K+1):
    if i >= weight[0]:
        dp[0][i] = value[0]
    else:
        dp[0][i] = 0

# 遍历dp数组
# 先遍历 行,再遍历 列(反之也可以)
for i in range(1,M):
    for j in range(1,K+1):
        if j < weight[i]:   # 放不下去
            dp[i][j] = dp[i-1][j]
        else:               # 可以放下去,看放不放(比较总价值量)
            dp[i][j] = max(dp[i-1][j] , dp[i-1][j-weight[i]] + value[i])
# 打印
print(f"dp 数组 = {dp}")
print(f"容量为 {K} 的背包 所能存放的最大商品价值量 是{dp[M-1][K]}")
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值