01背包问题
如果你没有动态规划基础请先看 动态规划基础
题目
有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。最多一次 (这个就是01背包问题的主要特点了)
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000
0<vi,wi≤1000
输入样例
1 | 4 5 |
输出样例:
1 | 8 |
思路
其实思路很简单,就是构造一个网格,举个例子:
就用样例数据,构建好的dp数组为:
容量为0 | 容量为1 | 容量为2 | 容量为3 | 容量为4 | 容量为5 | |
---|---|---|---|---|---|---|
可选物品0 | 0 | 0 | 0 | 0 | 0 | 0 |
可选物品1(1,2) | 0 | 2 | 2 | 2 | 2 | 2 |
可选物品2(2,4) | 0 | 2 | 4 | 6 | 6 | 6 |
可选物品3(3,4) | 0 | 2 | 4 | 6 | 6 | 8 |
可选物品4(4,5) | 0 | 2 | 4 | 6 | 6 | 8 |
构造的状态就是dp[i][j]
,在可选 i
件物品,且有 j
的容量的情况下的最大价值。
我们先维护 i
也就是将有 i
件物品的所有容量情况计算出来。当新添加一个物品是,有如下两种操作:
不拿
不拿就相当于是没有新添加这件物品,它就是等于没有这个物品在这个容量时的价值。
即
dp[i][j] = dp[i-1][j]
拿
拿了的话容量就会减少,我们要先判断是否可以拿,所以需要先判断容量
j >= vi
时才可拿如果可以拿就要判断拿了之后价值是否会有提升,拿了之后容量变成了
j - vi
,所以就相当于当前物品的价值 加上 没有这个物品且容量为j - vi
时的最优价值。即dp[i][j] = dp[i-1][j-vi] + wi
最终还要判断到底拿不拿,就是一个比较就行啦,所以维护状态,或者说状态转移方程就是:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-vi] + wi)
代码
1 |
|
其实还可以做优化,可自行思考。或者借鉴在 完全背包问题中的优化思路
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 秋白's Blog!
评论