题目描述:有
n
n
n件物品和一个容量为
v
v
v的背包,每个物品放进背包需要占用
S
i
S_i
Si的空间,可以得到
W
i
W_i
Wi的价值,放入一些物品使得价值最大,求最大值
分析:
状态设计:
明显的发现这个问题与
v
,
S
i
,
W
i
v,S_i,W_i
v,Si,Wi有关,于是可以将空间开出一维,价值用
F
F
F数组的值表示,设
F
j
F_{j}
Fj表示恰好占用
j
j
j空间的最大价值
因为
D
P
DP
DP要从小问题得到大问题的解,由于物品排列的先后顺序不会影响答案,就可以加多一维
i
i
i,表示
F
i
,
j
F_{i,j}
Fi,j前
i
i
i个物品中,占用空间恰好为
j
j
j的最大价值
转移方程:
假设当前我们要求
F
i
,
j
F_{i,j}
Fi,j,那么对于第
i
i
i个物品,就有取和不取,于是就有
F
i
,
j
=
{
F
i
−
1
,
j
(
不
取
)
(
0
⩽
j
⩽
v
)
F
i
−
1
,
j
−
S
i
+
W
i
(
取
)
(
s
i
⩽
j
⩽
v
)
F_{i,j}=\left\{ \begin{aligned} F_{i-1,j} (不取)(0\leqslant j \leqslant v)\\ F_{i-1,j-S_i}+W_i (取)(s_i\leqslant j \leqslant v)\\ \end{aligned} \right.
Fi,j={Fi−1,j(不取)(0⩽j⩽v)Fi−1,j−Si+Wi(取)(si⩽j⩽v)
于是枚举
i
,
j
i,j
i,j即可解决问题
时空优化:
时间上复杂度为
O
(
n
v
)
O(nv)
O(nv),无法优化
空间上复杂度为
O
(
n
v
)
O(nv)
O(nv),发现
F
i
,
j
F_{i,j}
Fi,j只与
F
i
−
1
,
j
(
0
⩽
j
⩽
v
)
F_{i-1,j(0\leqslant j \leqslant v)}
Fi−1,j(0⩽j⩽v)有关,于是可以把
i
i
i用滚动数组滚掉。
题目描述:题目描述:有
n
n
n种物品和一个容量为
v
v
v的背包,每种物品放一个进背包需要占用
S
i
S_i
Si的空间,可以得到
W
i
W_i
Wi的价值,放入一些物品使得价值最大,每种物品可以有无数个(空间大小要满足条件),求最大值
分析:
状态设计:
跟
01
01
01背包同理,设
F
i
,
j
F_{i,j}
Fi,j表示前
i
i
i种物品恰好占用
j
j
j空间物品的最大价值
转移方程:
假设当前选择到第
i
i
i种物品,要选择
k
k
k个,那么
F
i
,
j
F_{i,j}
Fi,j可能由
F
i
−
1
,
j
−
k
∗
S
i
F_{i-1,j-k*S_i}
Fi−1,j−k∗Si,或者直接继承
F
i
−
1
,
j
F_{i-1,j}
Fi−1,j
时空优化:
原时间复杂度为
O
(
n
v
∑
i
=
1
n
(
v
S
i
)
)
O(nv\sum_{i=1}^n(\frac{v}{S_i}))
O(nv∑i=1n(Siv)),空间为
O
(
n
v
)
O(nv)
O(nv)
现在考虑优化,假设有两种状态分别为
F
i
,
j
−
S
i
,
F
i
,
j
F_{i,j-S_i},F_{i,j}
Fi,j−Si,Fi,j,那我们在
D
P
DP
DP,发现其实它们只有
F
i
,
j
−
S
i
F_{i,j-S_i}
Fi,j−Si的差别,于是考虑减少次数
发现
F
i
,
j
−
S
i
F_{i,j-S_i}
Fi,j−Si已经把除了
F
i
,
j
−
S
i
F_{i,j-S_i}
Fi,j−Si之外的所有
F
i
,
j
F_{i,j}
Fi,j要考虑的状态都考虑了,所以我们发现可以把
k
k
k去掉,从小到达枚举
j
j
j,每次只需转移
F
i
,
j
=
F
i
,
j
−
S
i
F_{i,j}=F_{i,j-S_i}
Fi,j=Fi,j−Si。注意要考虑不取的情况,即
F
i
,
j
=
F
i
−
1
,
j
F_{i,j}=F_{i-1,j}
Fi,j=Fi−1,j
在加上一个滚动数组把
i
i
i滚掉,时间复杂度
O
(
n
v
)
O(nv)
O(nv),空间复杂度
O
(
v
)
O(v)
O(v)
题目描述:有
n
n
n种物品和一个容量为
v
v
v的背包,每种物品放一个进背包需要占用
S
i
S_i
Si的空间,可以得到
W
i
W_i
Wi的价值,放入一些物品使得价值最大,每种物品有
T
i
T_i
Ti个(空间大小要满足条件),求最大值
分析:
状态设计:
同完全背包,设
F
i
,
j
F_{i,j}
Fi,j表示前
i
i
i种物品恰好占用
j
j
j空间物品的最大价值
转移方程:
这个问题可以看作,是一个完全背包,只不过把有每种
v
/
S
i
v/S_i
v/Si个,改成了
T
i
T_i
Ti,可以按完全背包朴素的方法做,
F
i
,
j
F_{i,j}
Fi,j可能由
F
i
−
1
,
j
−
k
∗
T
i
F_{i-1,j-k*T_i}
Fi−1,j−k∗Ti,或者直接继承
F
i
−
1
,
j
F_{i-1,j}
Fi−1,j
时空优化:
原时间复杂度为
O
(
n
v
∑
i
=
1
n
(
v
S
i
)
)
O(nv\sum_{i=1}^n(\frac{v}{S_i}))
O(nv∑i=1n(Siv)),空间为
O
(
n
v
)
O(nv)
O(nv)
考虑
k
k
k的问题,其实最多就
T
i
T_i
Ti个,考虑到用几个
2
0
2^0
20~
2
t
2^t
2t可以表示出
2
t
+
1
−
1
2^{t+1}-1
2t+1−1里的所有数,所以将第
i
i
i种物品变成
log
2
T
i
+
2
\log_2T_i+2
log2Ti+2个物品,设
log
2
T
i
=
g
\log_2T_i=g
log2Ti=g,
1
1
1 ~
g
−
1
g-1
g−1是体积为
2
t
2^t
2t价值为
W
i
∗
2
t
W_i*2^t
Wi∗2t的物品,
g
g
g个物品是体积为
T
i
−
2
g
+
1
T_i-2^g+1
Ti−2g+1价值为
W
i
∗
(
T
i
−
2
g
+
1
)
W_i*(T_i-2^g+1)
Wi∗(Ti−2g+1)的物品,于是这样就可以像
01
01
01背包一样做了
滚掉
i
i
i
时间复杂度
O
(
n
v
∑
i
=
1
n
log
2
(
v
S
i
)
)
O(nv\sum_{i=1}^n\log_2(\frac{v}{S_i}))
O(nv∑i=1nlog2(Siv)),空间复杂度
O
(
v
)
O(v)
O(v)