有 N 种物品和一个容量是 V 的背包,每种物品都有无限件可用。
第
i
i
i 种物品的体积是
v
i
v_i
vi,价值是
w
i
w_i
wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
两个整数
N
,
V
N,V
N,V 用空格隔开,分别表示物品种数和背包容积。
该题与01背包的不同在于所有的物品都是无限的,即每个物品可以装多次。
朴素做法这里我们就不说了。直接给个简化的算法。
#include <iostream>
#include <cstring>
#include <algorithm>
#define MAX 1010
using namespace std;
int f[MAX];
int v[MAX], w[MAX];
int N, V;
int main()
{
cin >> N >> V;
for (int i = 1; i <= N; i++)
cin >> v[i] >> w[i];
for (int i = 1; i <= N; i++)
for (int j = v[i]; j <= V; j++)
f[j] = max(f[j], f[j - v[i]] + w[i]);
cout << f[V] << endl;
}
细心一点,我们就注意到,这与01背包的区别就是对于 j j j 的遍历成了顺序遍历。这是为什呢?
因为我们此时的物品已经是无限个了,所以在到达第 i i i 个物品时,我们要考虑能装多少个第 i i i 个物品。而正向遍历,在考虑 f ( j ) f(j) f(j) 时,也考虑了 f ( j − v i ) f(j-v_i) f(j−vi) , 而 j − v i < j j-v_i < j j−vi<j ,故小于 j 的情况都考虑过了(包括 j j j)。而01背包恰好相反,它不能考虑 f ( j ) f(j) f(j) 的存在,故用反向遍历。