背包问题是一个1896年提出的经典问题,在100余年的时间里出现了许多变种,而他最早的形式是01背包。
###大意是指背包容量V,有n个物体每个物体体积
V
i
V_i
Vi,质量
M
i
M_i
Mi,问在空间允许下,可装入物体的最大质量总和为多少.
不难贪心的想到当物体的密度越大时,他的效益也就越高,那么…
学过背包的朋友看到这里可能就要笑了,因为这个贪心明显是错的,但至于我为什么要提这个贪心,后面再说。
为了防止误导大家,我先讲一下01背包的正解:
####枚举:不难发现状态数只有
2
n
2^n
2n个,然后…
####动态规划:定义
d
p
i
,
j
dp_{i,j}
dpi,j为第放入i个物体,耗用j的空间的最大质量,O(Vn)即可做出来
ps:动态规划第二维可以滚动
#线性规划
看完正解之后,然后我来讲一讲背包问题的本质:
##背包问题本质是一个线性规划问题
##背包问题本质是一个线性规划问题
##背包问题本质是一个线性规划问题
重要的事说3遍。
关于线性规划,如果学过高中必修5,在不等式那一章有提到,其中的例题就是一个n=2的完全背包问题
如果没有学过必修5,也没有问题,线性规划是一个极易理解的方法。
不过,首先,你要确保你学过平面直角坐标系(-_-)///
对于平面上的一个点,我们可以用向量(
x
0
x_0
x0,
y
0
y_0
y0)来表示,
对于拓展到高维的情况,也可以用一个对应维度的向量表达:(
t
0
t_0
t0,
t
1
t_1
t1,
t
2
t_2
t2,…,
t
n
t_n
tn)
对于平面上的一条直线我们可以很容易表示出起显函数表达式:
y
=
a
x
+
b
y = ax + b
y=ax+b
我们称这种形式为斜截式,这种形式对于斜率为正负无穷的直线无法表示
故在此引入直线的一般式:
A
x
+
B
y
+
C
=
0
Ax + By + C = 0
Ax+By+C=0,又称为直线方程
然后我们将其向三维推广
A
x
+
B
y
+
C
z
+
D
=
0
Ax+By+Cz+D=0
Ax+By+Cz+D=0
…
wait,不对啊,这个方程当x值确定为
x
0
x_0
x0时,
B
y
+
C
z
+
(
A
x
0
+
D
)
=
0
By+Cz+(Ax_0+D)=0
By+Cz+(Ax0+D)=0
这时,y与z的表达式为直线,那岂不是,对于每一个x的值,都有一个在y,z轴上的直线,
那是…
没错,你猜的没错,那就是平面,于是乎你得到了一个平面的表达式,
那向高维推广呢,
A
0
t
0
+
A
1
t
1
+
A
2
t
2
+
.
.
.
+
A
n
t
n
+
A
n
+
1
=
0
A_0t_0+A_1t_1+A_2t_2+...+A_nt_n+A_{n+1}=0
A0t0+A1t1+A2t2+...+Antn+An+1=0
这个方程可以描述一个(n-1)维的分割线,可以将一个n维物体分作两份。
看到这,你可能会说,说了半天,都没有扯到一点线性规划。
别急,这不是在打铺垫吗,你在仔细看看这句话:
一个(n-1)维的分割线,可以将一个n维物体分作两份。
对于一个直线(1维),可以将一个平面(2维)分割成两个半平面,
wait,是不是发现了什么,
被直线分割的两个半平面可以分别用两个二元不等式来表示:
A
x
+
B
y
+
C
<
0
Ax+By+C<0
Ax+By+C<0
A
x
+
B
y
+
C
>
0
Ax+By+C>0
Ax+By+C>0
如果放过来表示,那么这个二元不等式,也可以用半平面来表示,
那么二元不等式的组的解集,即可以用半平面交来表示,
那拓展到n维,岂不是:
一个n元不等式组的解集,可以用“n维物体”交,来表示
至于n维物体到底长啥样,我是想象不出来,但这种方法确实使得一些不等式问题变得形象起来。
那这种方法叫什么呢?
答:线性规划
那至于01背包问题,我们可以转化为以下不等式组
n
i
n_i
ni表示第i个物品取几个
0
<
=
v
1
n
1
+
v
2
n
2
+
v
3
n
3
+
.
.
.
+
v
n
n
n
<
=
V
0<=v_1n_1+v_2n_2+v_3n_3+...+v_nn_n<=V
0<=v1n1+v2n2+v3n3+...+vnnn<=V
0
<
=
n
i
<
=
1
对
任
意
i
成
立
0<=n_i<=1 \ \ \ 对任意i成立
0<=ni<=1 对任意i成立
不难发现这些不等式都可以转化成一个n维物体,这些物体的交,即为线性规划的可行域。
wait,背包不是要求一个最大值吗,跟一个n维物体有什么关系。
我们先来写一下对于某一种选择情况 ( n 1 , n 2 , . . . , n n ) (n_1,n_2,...,n_n) (n1,n2,...,nn)的收益方程
w
=
m
1
n
1
+
m
2
n
2
+
m
3
n
3
+
.
.
.
+
m
n
n
n
w=m_1n_1+m_2n_2+m_3n_3+...+m_nn_n
w=m1n1+m2n2+m3n3+...+mnnn
转化为:
m
1
n
1
+
m
2
n
2
+
m
3
n
3
+
.
.
.
+
m
n
n
n
−
w
=
0
m_1n_1+m_2n_2+m_3n_3+...+m_nn_n-w=0
m1n1+m2n2+m3n3+...+mnnn−w=0
不难看出
n
i
n_i
ni为自变量,这个方程即可转化为一个n-1维物体,就是可以将刚刚那个n维空间分成两份的东西
感性理解一波,即可发现,背包问题最优的解即为,那个n维凸包,在这个n-1维的斜率下的投影,
在可行域中最低的那个那个点.
那岂不是背包问题成为以一个凸包问题。
这个时候我们想一想刚开始我提的那个贪心算法,不正是沿着凸包的最优解吗?
这个时候,似乎整个世界都变得有些迷,那个贪心是对的吗?
但这个是时候,你就要仔细想想,背包问题,是一个,整数,问题
###整数,问题!
你似乎发现的整个事情的玄机,原来,贪心的错误在这里,那么线性规划如何解决背包问题,在此,我给出一个最暴力的方法扫描凸包旁的整点,O(
∏
i
n
(
V
n
i
)
\prod^n_i(\frac{V}{n_i})
∏in(niV));似乎有点大,但是似乎也没有更好的解,却能让你更好的了解背包问题的本质。
然而线性规划的作用远不如此,更多用处还等大家慢慢探究.