背包
背包
一、算法设计
目标函数
\[\sum_{j=1}^{n}v_jx_j
\]
约束条件
\[\sum_{j=1}^{n}w_jx_j\leq W \quad\quad\quad\quad\sum_{j=1}^{n}c_jx_j\leq V
\]
约束条件有两个,一个是总重量小于等于W,另一个是总体积小于等于V
递推关系
\[F_k(y,z)=max\{F_k(y-w_k,z-c_k)+v_k,F_{k-1}(y,z)\} \\
\\
\]
F_k(y,z)表示前k种物品在重量限制y和体积限制z的共同作用下的最大价值。此时有两种情况,一种是不装第k种商品,它的总价值就和前(k-1)种物品在背包(y,z)情况下的总价值,即为F_k-1(y,z);另一种是装第k种商品,它的价值就为装此商品前的背包价值F(y-w,z-c)加上此物品的价值。
边界条件
\[F_0(y,z)=0\\
F_i(y,z)=0 \qquad y=0\quad or\quad z=0\\
F_1(y,z)=min\{\lfloor y/w_1 \rfloor,\lfloor z/c_1 \rfloor\}*v_1
\]
背包没有商品时,价值为0。当重量或体积约束为0时,价值也为0。第一种物品的数量要同时考虑到重量和体积的约束,所以要选最小值。其中还要注意y,z需要大于0,否则在边界位置没有意义。
标记函数
\[i_k(y,z)=\begin{cases}
i_{k-1}(y,z) && F_{k-1}(y,z)>F_k(y-2_k,z-c_k)+v_k\\
k && F_{k-1}\leq F_k(y-w_k,z-c_k)+v_k
\end{cases}
\]
二、算法实现
随机生成数据
import numpy as np
num=20
min=1
max=20min
a=np.random.randint(min,max,(num,3))
np.savetxt("data.txt",a,fmt="%d",delimiter=' ')
物品的的种类为num,随机生成num行3列的数组,第一列为价值,第二列为重量,第三列为体积。存入'data.txt'文件里
取数据,并初始化
a=np.array([[0,0,0]],dtype=np.int)
b=np.loadtxt("data.txt",delimiter=' ',dtype=np.int)
a=np.append(a,b,axis=0)
F=np.zeros((a[:,0].size,W+1,V+1),dtype=np.int)
for i in range(0,W+1):
for j in range(0,V+1):
F[1,i,j]=min(i//a[1,1],j//a[1,2])*a[1,0]
i=np.zeros((a[:,0].size,W+1,V+1),dtype=np.int)
由于有边界条件,所以数据要从第一行开始存。F的大小为物品种类总体积总重量*,同时因为边界调节,每个坐标轴都要+1。标记数组i都要初始化为0(其实只有边界需要初始化,但是反正创建数组时都要初始化,就初始化一下吧)
优化数组
for k in range(1,a[:,0].size):
for y in range(1,W+1):
if y<a[k,1]:
F[k,y,:]=F[k-1,y,:]
continue
for z in range(1,V+1):
if z<=a[k,2]:
F[k,y,z]=F[k-1,y,z]
continue
F[k,y,z]=max(F[k,y-a[k,1],z-a[k,2]]+a[k,0],F[k-1,y,z])
y和z在0的时候没有意义,所以从一开始。注意y和z需要大于0,所以不满足的情况要跳过。
标记数组
for k in range(1,a[:,0].size):
for y in range(1, W+1):
if y < a[k, 1]:
i[k,y,:]=i[k-1,y,:]
continue
for z in range(1, V+1):
if z <= a[k, 2]:
i[k,y,z]=i[k-1,y,z]
continue
if F[k-1,y,z]>F[k,y-a[k,1],z-a[k,2]]+a[k,0]:
i[k,y,z]=i[k-1,y,z]
else:
i[k,y,z]=k
和优化数组的要点一样,y和z要从1开始。不满足y和z大于0的情况要跳过。
追踪过程
x=np.zeros(a[:,0].size,dtype=np.int)
y=W
z=V
k=a[:,0].size-1
while(i[k,y,z]!=0):
j=i[k,y,z]
x[j]=1
y-=a[j,1]
z-=a[j,2]
while(i[j,y,z]==j):
y -= a[j, 1]
z -= a[j, 2]
x[j]+=1
三、算法分析
数据及结果
v,w,c
[[7 6 7]
[4 5 1]
[7 7 2]
[5 7 1]
[7 5 5]]
重量限制 10 体积限制 15
第 5 件物品 2 件
总价值为 14
优化函数
[[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7 7]
[ 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7 7]
[ 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7 7]
[ 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7 7]
[ 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7 7]]
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
[ 0 4 4 4 4 4 4 7 7 7 7 7 7 7 7 7]
[ 0 4 4 4 4 4 4 7 7 7 7 7 7 7 7 7]
[ 0 4 4 4 4 4 4 7 7 7 7 7 7 7 7 7]
[ 0 4 4 4 4 4 4 7 7 7 7 7 7 7 7 7]
[ 0 4 8 8 8 8 8 8 8 8 8 8 8 8 8 8]]
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
[ 0 4 4 4 4 4 4 7 7 7 7 7 7 7 7 7]
[ 0 4 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 4 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 4 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 4 8 8 8 8 8 8 8 8 8 8 8 8 8 8]]
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4]
[ 0 4 4 4 4 4 4 7 7 7 7 7 7 7 7 7]
[ 0 5 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 5 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 5 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 5 8 8 8 8 8 8 8 8 8 8 8 8 8 8]]
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 4 4 4 4 7 7 7 7 7 7 7 7 7 7 7]
[ 0 4 4 4 4 7 7 7 7 7 7 7 7 7 7 7]
[ 0 5 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 5 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 5 7 7 7 7 7 7 7 7 7 7 7 7 7 7]
[ 0 5 8 8 8 8 11 11 11 11 14 14 14 14 14 14]]]
标记函数
[[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1]
[0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1]
[0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1]
[0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1]
[0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1]]
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
[0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1]
[0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1]
[0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1]
[0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1]
[0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]]
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
[0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1]
[0 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
[0 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
[0 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
[0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]]
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
[0 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1]
[0 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
[0 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
[0 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3]
[0 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2]]
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[0 2 2 2 2 5 5 5 5 5 5 5 5 5 5 5]
[0 2 2 2 2 5 5 5 5 5 5 5 5 5 5 5]
[0 4 3 3 3 5 5 5 5 5 5 5 5 5 5 5]
[0 4 3 3 3 5 5 5 5 5 5 5 5 5 5 5]
[0 4 3 3 3 5 5 5 5 5 5 5 5 5 5 5]
[0 4 2 2 2 2 5 5 5 5 5 5 5 5 5 5]]]
四、时间复杂度分析
运行时间
W=100 #约束条件
V=150
mi=1 #价格体积重量数据的范围
ma=10
因为此题的可变条件较多,所以我就选择了一个最不受干扰的数据———物品种类来做分析。由此可见,运行时间基本和物品种类成线性关系。
时间复杂度
O(nWV),表面上开始这样的。但是同书上所说其实和W、V在电脑中占的存储空间有关,所以未伪多项式时间。但如同我上面的图片所示。在附加数据不变的情况下,基本与物品种类n成正比