目录
详细需求
要求在一个物品集合中选择合适的物品放入背包,在放入背包中的物品总重量不超过背包容量的前提下,希望放入背包的物品总价值最大。根据是否允许部分物品放入背包的要求,背包问题可以分为分数背包问题和0-1背包问题。
对于分数背包问题,可以通过设计贪心算法得到问题实例的最优解。对于0-1背包问题,该问题已经被证明为NP-Hard,即不存在多项式时间算法那求解,但可以通过贪心算法得到问题的近似解,或者通过蛮力法、动态规划法得到问题的最优解。
详细代码
文件结构
fuction.py
import numpy
def input_s():
beibao_rongliang = int(input("输入背包容纳重量:"))
shu_liang = int(input("输入商品数量:"))
weights = []
values = []
for i in range(shu_liang):
weight = int(input("输入第" + str(i + 1) + "个商品重量:"))
value = int(input("输入第" + str(i + 1) + "个商品价值:"))
weights.append(weight)
values.append(value)
return values, weights, beibao_rongliang
def greedy_for_fs(values, weights, beibao_rongliang):
print("**************贪心算法分数****************")
print("--------------性价比排序----------------")
xing_jiabi = []
for i in range(len(weights)):
xing_jiabi.append(values[i] / weights[i])
xing_jiabi = numpy.array(xing_jiabi)
bigtoSmall = numpy.argsort(xing_jiabi)[::-1]
values_new = []
weights_new = []
zong_jiazhi = 0
for i in range(len(bigtoSmall)):
print("价值:", values[bigtoSmall[i]], "重量:", weights[bigtoSmall[i]])
for i in range(len(bigtoSmall)):
if (beibao_rongliang - weights[bigtoSmall[i]] >= 0):
values_new.append(values[bigtoSmall[i]])
weights_new.append(weights[bigtoSmall[i]])
zong_jiazhi += values[bigtoSmall[i]]
beibao_rongliang -= weights[bigtoSmall[i]]
else:
values_new.append(values[bigtoSmall[i]])
weights_new.append(beibao_rongliang)
zong_jiazhi += beibao_rongliang / weights[bigtoSmall[i]] * values[bigtoSmall[i]]
break
print("--------------背包物品----------------")
for i in range(len(values_new)):
print("价值:", values_new[i], "重量:", weights_new[i])
print("总价值:", zong_jiazhi)
def greedy_for_01(values, weights, beibao_rongliang):
print("**************贪心算法01****************")
print("--------------性价比排序----------------")
xing_jiabi = []
for i in range(len(weights)):
xing_jiabi.append(values[i] / weights[i])
xing_jiabi = numpy.array(xing_jiabi)
bigtoSmall = numpy.argsort(xing_jiabi)[::-1]
values_new = []
weights_new = []
zong_jiazhi = 0
for i in range(len(bigtoSmall)):
print("价值:", values[bigtoSmall[i]], "重量:", weights[bigtoSmall[i]])
for i in range(len(bigtoSmall)):
if (beibao_rongliang - weights[bigtoSmall[i]] >= 0):
values_new.append(values[bigtoSmall[i]])
weights_new.append(weights[bigtoSmall[i]])
zong_jiazhi += values[bigtoSmall[i]]
beibao_rongliang -= weights[bigtoSmall[i]]
else:
break
print("--------------背包物品----------------")
for i in range(len(values_new)):
print("价值:", values_new[i], "重量:", weights_new[i])
print("总价值:", zong_jiazhi)
def testout(values, weights, beibao_rongliang):
print("--------------测试输出----------------")
print("背包容纳重量:", beibao_rongliang)
for i in range(len(weights)):
print("价值:", values[i], "重量:", weights[i])
def erToten(num, length):
num_list = []
while (num / 2 != 0):
num_list.insert(0, num % 2)
num = num // 2
if (len(num_list) < length):
for i in range(length - len(num_list)):
num_list.insert(0, 0)
return num_list
def brute_for_01(values, weights, beibao_rongliang):
print("**************暴力算法01****************")
zong_jiazhi = 0
condition = []
for i in range(2 ** len(values)):
condition.append(erToten(i, len(values)))
for i in condition:
linshi_jiazhi = 0
zong_zhongliang = 0
print(i, end="")
for j in range(len(i)):
if (i[j] == 1):
zong_zhongliang += weights[j]
linshi_jiazhi += values[j]
print("临时价值:", linshi_jiazhi)
if (linshi_jiazhi > zong_jiazhi and zong_zhongliang <= beibao_rongliang):
zong_jiazhi = linshi_jiazhi
print("最有价值:", zong_jiazhi)
def dynamic_for_01(values,weights,beibao_rongliang):
print("**************动态规划01****************")
value=[]
for i in range(len(values)+1):
value_linshi=[]
for j in range(beibao_rongliang+1):
value_linshi.append(0)
value.append(value_linshi)
# for i in value:
# print(i)
for i in range(1,len(values)+1):
for j in range(1,beibao_rongliang+1):
#不放入
value[i][j]=value[i-1][j]
#放入
#确保当前背包的剩余容量大于或等于第 i 个物品的重量 并且放入时,最优解是第 i 个物品的价值 values[i - 1]
# 加上剩余容量 w - weights[i - 1] 时的最优解,即 values[i - 1] + dp[i - 1][w - weights[i - 1]]。
if j >= weights[i - 1] and value[i][j] < value[i - 1][j - weights[i - 1]] + values[i - 1]:
value[i][j] = value[i - 1][j - weights[i - 1]] + values[i - 1]
for i in value:
print(i)
x = [False for i in range(beibao_rongliang)]
for i in range(len(values), 0, -1):
if value[i][j] > value[i - 1][j]:
x[i - 1] = True
j -= weights[i - 1]
print('所装物品为:',end="")
for i in range(len(values)):
if x[i]:
print('第', i + 1, '个,', end='')
print("最大价值:",value[len(values)][beibao_rongliang])
def dynamic_for_01_youhua(values, weights, beibao_rongliang):
print("**************动态规划优化01****************")
#这里引入了一个名为 memo 的二维数组,用于存储已经计算过的子问题的结果。在 dp 函数中,
# 首先检查 memo[i][w] 是否已经计算过,如果是,则直接返回该值,避免重复计算。如果没有计算过,
# 则按照原有的递归逻辑计算,并将结果存入 memo[i][w] 中。
n = len(weights)
memo = [[-1 for i in range(beibao_rongliang + 1)] for i in range(n + 1)]
def dp(i, w):
if i == 0 or w == 0:
return 0
if memo[i][w] != -1:
return memo[i][w]
if weights[i - 1] > w:
memo[i][w] = dp(i - 1, w)
else:
memo[i][w] = max(dp(i - 1, w), values[i - 1] + dp(i - 1, w - weights[i - 1]))
return memo[i][w]
print("最大价值:",dp(n, beibao_rongliang))
Lab3.py
import fuction as ft
# values, weights, beibao_rongliang = ft.input_s()
values=[1,7,5,8]
weights=[4,2,3,4]
beibao_rongliang=7
ft.testout(values,weights,beibao_rongliang)
ft.greedy_for_fs(values, weights, beibao_rongliang)
ft.greedy_for_01(values,weights,beibao_rongliang)
ft.brute_for_01(values,weights,beibao_rongliang)
ft.dynamic_for_01(values,weights,beibao_rongliang)
ft.dynamic_for_01_youhua(values,weights,beibao_rongliang)