1. 问题描述:
有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。第 i 种物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0 < N,V ≤ 1000
0 < vi,wi ≤ 1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例:
10
来源:https://www.acwing.com/problem/content/3/
2. 思路分析:
这道题目属于完全背包的裸题(模板题),直接使用完全背包的模板即可解决,为了节省空间我们可以使用一维的动态规划解决,其实完全背包问题与01背包问题是类似的,只是完全背包问题拿取的每个物品都是无限的。在递推的过程中一维的01背包第二层循环是逆序遍历背包的容量,逆序遍历的目的是为了保证之前拿取的每一个物品是只拿取过0次或者是1次的,而完全背包恰恰相反我们需要保证之前拿取的物品是有若干次的,所以在正序遍历背包容量的时候实际上是在尝试1 * v[i],2 *v[i]...k * v[i],这样表示的是在背包最大容量的前提下允许拿取当前物品有k次,并且在拿取物品的时候是递推得到当前背包容量的前提下能够拿取物品的最大价值。其实可以结合01背包问题的代码进行记忆,完全背包问题是正序遍历背包容量,01背包是逆序遍历背包容量。
3. 代码如下:
if __name__ == '__main__':
n, v = map(int, input().split())
vi, wi = list(), list()
for i in range(n):
a, b = map(int, input().split())
vi.append(a)
wi.append(b)
dp = [0] * (v + 1)
# 正序遍历
for i in range(n):
for j in range(vi[i], v + 1):
dp[j] = max(dp[j], dp[j - vi[i]] + wi[i])
print(dp[-1])