文章目录
网上关于这个方面的python代码比较少,所以分别用暴力、动态规划、回溯、分支限界实现了一下关于0-1背包问题(不能只取一部分物品)。
1.暴力法
1.1 设计思想
蛮力法即找出所有可能的解,在所有的解中选择最优解。由于物品众多,不可能采用for循环的形式,所以这个实验考虑使用递归调用的方式找出所有满足条件的解,设置一个记录最大价值的变量valuesMax记录最优解时的价值,设置一个visitMax数据记录最优解时物品的状态是否装入背包。具体的递归过程设计为:从第一个物品开始遍历所有的物品,在每次遍历中,判断物品是否装入,如果没有装入,判断背包的剩余容量能否装入此物品,如果可以,则将visit[i]置为1,然后更新背包剩余容量,进行递归调用。每次进入递归函数时,将当前的背包价值与valuesMax进行比较,如果当前值大于valuesMax,则将当前值赋值给valuesMax,并将visit赋值给visitMax。
1.2代码实现
#蛮力法解0/1背包问题
import numpy as np
class brute:
def __init__(self, w, v, c):
'''
:param w: 重量
:param v: 价值
:param c: 背包容量
'''
self.w = w
self.v = v
self.c = c
def brute_force(self, visit, values, currentV):
'''
:param visit: 记录物品装或者不装的数组
:param values: 记录当前的价值
:param currentV: 记录当前的体积
:return:
'''
global visitMax #全局变量,记录最大价值时物品的状态全
global valuesMax #局变量,记录最大价值
if(values > valuesMax):
valuesMax = values
visitMax = visit.copy()
self.v = np.array(self.v)
self.w = np.array(self.w)
for i in range(self.v.size):
if(visit[i] == 0):
if(self.w[i] > self.c - currentV):
continue
visit[i] = 1
self.brute_force(visit, values+self.v[i], currentV+self.w[i])
visit[i] = 0
return visit, values
b = brute(w=[6,5,4,1,2,3,9,8,7], v=[1,2,3,7,8,9,6,5,4], c=20)
visit = np.zeros(9)
valuesMax = 0
visitMax = visit.copy()
status = []
x = b.brute_force(visit, 0, 0)
for i in range(visitMax.size):
if(visitMax[i] != 0):
status.append(i+1)
print("最优解序号为:")
print(status)
print("最大值为:")
print(valuesMax)
1.3 实验结果
2.动态规划
2.1设计思想
使用动态规化填表。先求出最大值,定义了一个dynamic_programming返回值为建立的表。先建立表values[nums+1,c+1],行为第i个物品,列为背包容量,初始化,将values[i,0]与values[0,i]置为零。然后对于第i个物品开始,values[i,j]的值分为两种情况,如果背包得剩余容量不够当前物品得重量,则values[i,j]=values[i,j-1];如果当前剩余容量大于当前物品的重量,则如果(values[i-1, j] > values[i-1, j-=w[i - 1]] + =v[i - 1]),则values[i,j] = values[i-1, j],否则,values[i,j] = values[i-1, j-=w[i - 1]] + =v[i - 1]。values[num,c]即为最优值。对于找最优解下的每个物品的状态,设计一个loa