01 背包:Knapsack 1
背景
第一次在 AtCoder 上做到 01 背包,发现虽然是模板题,但自己写的时候还是卡了不少地方——主要是 Java 的数组类型和下标转换细节。
题目描述
给定 N 个物品,每个物品有重量 w[i] 和价值 v[i]。背包容量为 W,求能装入的最大总价值。
每个物品最多选一次,经典的 01 背包问题。
思路分析
01 背包的标准做法是用一维 DP 数组,容量从大到小遍历,保证每个物品只取一次。
转移方程:
1 | f[j] = max(f[j - w[i]] + v[i], f[j]) |
其中 f[j] 表示容量为 j 时能获得的最大价值。
关键细节:
- 数据范围较大,
f数组必须开long,否则会溢出 - Java 中数组下标必须是
int,而w[i]存为long时需要用(int)强转 - 空间上提前初始化一个足够大的数组(如
maxn = 100005),避免动态扩容
代码实现
1 | import java.util.Scanner; |
复杂度分析
- 时间复杂度:O(N × W),其中 N 为物品数,W 为背包容量
- 空间复杂度:O(W),使用一维滚动数组优化后的结果
小结
- 01 背包的一维写法要倒序遍历容量,这是核心套路
- Java 做题时注意
long数组和(int)类型转换,各语言的类型细节不同容易在这里耽误时间 - 初始化一个大数组而不是用
ArrayList或动态结构,在竞赛中更省心
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Alignm-ent!
