基础背包问题
01背包
有N种物品,第i种物品的体积是v[i],价值是w[i],每件物品最多只能选1件。有一个容量为V的背包,问将哪些物品装入背包,可使这些物品的总体积不超过背包,并且总价值最大,输出最大价值。
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int N, V;
std::cin >> N >> V;
std::vector<int> v(N+1), w(N+1);
for (int i = 1; i <= N; i++) {
std::cin >> v[i] >> w[i];
}
std::vector<int> dp1(V+1), dp2(V+1);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= V; j++) {
dp2[j] = dp1[j];
if (j >= v[i]) {
dp2[j] = std::max(dp2[j], w[i]+dp1[j-v[i]]);
}
}
std::swap(dp1, dp2);
}
std::cout << dp1[V] << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
完全背包
有N种物品,第i种物品的体积是v[i],价值是w[i],每种物品都有无数多件。有一个容量为V的背包,问将哪些物品装入背包,可使这些物品的总体积不超过背包,并且总价值最大,输出最大价值。
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int N, V;
std::cin >> N >> V;
std::vector<int> v(N+1), w(N+1);
for (int i = 1; i <= N; i++) {
std::cin >> v[i] >> w[i];
}
std::vector<int> dp1(V+1), dp2(V+1);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= V; j++) {
dp2[j] = dp1[j];
if (j >= v[i]) {
dp2[j] = std::max(dp2[j], w[i]+dp2[j-v[i]]);
}
}
std::swap(dp1, dp2);
}
std::cout << dp1[V] << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
多重背包
有N种物品,第i种物品的体积是v[i],价值是w[i],共有s[i]件。有一个容量为V的背包,问将哪些物品装入背包,可使这些物品的总体积不超过背包,并且总价值最大,输出最大价值。
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int N, V;
std::cin >> N >> V;
std::vector<int> nv{0};
std::vector<int> nw{0};
for (int i = 0; i < N; i++) {
int v, w, s;
std::cin >> v >> w >> s;
for (int i = 1; s > i; i *= 2) {
nv.push_back(i * v);
nw.push_back(i * w);
s -= i;
}
nv.push_back(s * v);
nw.push_back(s * w);
}
int nn = nv.size() - 1;
std::vector<int> dp1(V+1), dp2(V+1);
for (int i = 1; i <= nn; i++) {
for (int j = 1; j <= V; j++) {
dp2[j] = dp1[j];
if (j >= nv[i]) {
dp2[j] = std::max(dp2[j], nw[i]+dp1[j-nv[i]]);
}
}
std::swap(dp1, dp2);
}
std::cout << dp1[V] << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
分组背包
有N组物品,第i组物品有s[i]件,体积为v[i][j],价值为w[i][j],其中i是组号,j是组内编号,同一组内物品最多只能选1件。有容量为V的背包,问将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大,输出最大价值。
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int N, V;
std::cin >> N >> V;
std::vector<std::vector<int>> v(N+1), w(N+1);
for (int i = 1; i <= N; i++) {
int s;
std::cin >> s;
v[i].resize(s);
w[i].resize(s);
for (int j = 0; j < s; j++) {
std::cin >> v[i][j] >> w[i][j];
}
}
std::vector<int> dp1(V+1), dp2(V+1);
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= V; j++) {
dp2[j] = dp1[j];
for (int k = 0; k < v[i].size(); k++) {
if (j >= v[i][k]) {
dp2[j] = std::max(dp2[j], w[i][k]+dp1[j-v[i][k]]);
}
}
}
std::swap(dp1, dp2);
}
std::cout << dp1[V] << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}