题目描述:
有 N N N 种物品和一个容量是 V V V 的背包。
第 i i i 种物品最多有 s i si si 件,每件体积是 v i vi vi,价值是 w i wi wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和大。
输出大价值。
输入格式:
第一行两个整数,
N
N
N,
V
V
V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N N N 行,每行三个整数 v i vi vi, w i wi wi, s i si si,用空格隔开,分别表示第 i i i 种物品的体积、价值和数量。
输出格式:
输出一个整数,表示大价值。
数据范围: 输入样例: 输出样例: 本题的题目描述一看就是一道典型的背包题目 (如果对背包类题目不了解的可以先去读一下C++背包详解) 因为题目条件里给出了物品的数量 会发现这并不是01背包或完全背包 而是一种新的类型—多重背包 即每种物品可以取有限次 其实对于大多数动态规划类型的题目, 都可以通过样例从后往前推状态转移方程 背包容积:
V
=
5
V=5
V=5 依旧可以使用从后往前举例的做法 设
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示前
i
i
i 个物品用
j
j
j 的体积所获得的大价值 因为只需要调用本行和上一行的值,所以可以直接将二维压成一维,减少空间 即
f
[
j
]
f[j]
f[j] 对于第
4
4
4 个物品来说, 如果取第
4
4
4 个物品: 那么体积减少
4
4
4,价值增加
5
5
5,但仍旧需要判断物品是否用光 如果不取第
4
4
4 个物品,那么体积不变(
f
[
j
]
f[j]
f[j] ) 可得状态转移方程:
f
[
j
]
=
m
a
x
(
f
[
j
]
,
f
[
j
−
v
[
i
]
]
+
w
[
i
]
)
f[j]=max(f[j],f[j-v[i]]+w[i])
f[j]=max(f[j],f[j−v[i]]+w[i]) 这时,还有一个问题需要考虑:物品数量怎么处理? 这时我们就需要有一种思路 将多重背包拆分成01背包 即把多个相同物品看做一个个不同物品(实质是相同的) 这样只需要在外面循环一遍数量就可以了 本题跟多重背包题面一致,但数据范围加大了非常多 如果用多重背包拆分01背包的方法会时间超限 所以需要进行优化 在讲解之前,我们要明白一个知识点: 任何一个正整数都可以拆分成 1,2,4…… 2k-1,n-2k+1之和 其中
k
k
k 为满足 n-2k+1>0的大整数 比如
18
=
1
+
2
+
4
+
8
+
3
18=1+2+4+8+3
18=1+2+4+8+3 那么我们可以把原本拆成01背包的方法改为拆成二进制形式 还是以
18
18
18 为例子,假设有一种物品价值为
2
2
2,数量为
18
18
18 那么物品数量就可拆成
1
,
2
,
4
,
8
,
3
1,2,4,8,3
1,2,4,8,3 的形式 价值可拆为
1
∗
2
,
2
∗
2
,
4
∗
2
,
8
∗
2
,
3
∗
2
1*2,2*2,4*2 , 8*2,3*2
1∗2,2∗2,4∗2,8∗2,3∗2 的形式 那么时间复杂度就转化为了
l
o
g
log
log 级别 你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
0
<
N
,
V
≤
100
04 5
1 2 3
2 4 1
3 4 3
4 5 2
思路10
编号 体积 价值 数量 1 1 2 3 2 2 4 1 3 3 4 3 4 4 5 2
(
f
[
j
−
4
]
f[j-4]
f[j−4] )
例题:Acwing 5.多重背包2
思路#include
谢谢观看!
#include
本文名称:C++背包问题详解2-创新互联
地址分享:http://kswsj.cn/article/dohode.html