背包问题代码模板
01背包
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef long long LL;
const int MAXN = 1e3 + 5;
int f[MAXN][MAXN];
int a1[MAXN];
int a2[MAXN];
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a1[i], &a2[i]);
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j <=m; j++) {
f[i][j] = f[i - 1][j];
if (j >= a1[i])
f[i][j] = max(f[i][j], f[i-1][j - a1[i]] + a2[i]);
}
}
printf("%d\n", f[n][m]);
return 0;
}
完全背包
基础版
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 1e3 + 5;
int f[N][N];
int a1[N];
int a2[N];
int main() {
int n, v;
scanf("%d%d", &n, &v);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a1[i], &a2[i]);
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= v; j++) {
for (int k = 0; k * a1[i] <= j; k++) {
f[i][j] = max(f[i][j], f[i - 1][j - k * a1[i]] + k * a2[i]);
}
}
}
printf("%d\n", f[n][v]);
return 0;
}
完全背包优化1
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 1e3 + 5;
int f[N][N];
int a1[N];
int a2[N];
int main() {
int n, v;
scanf("%d%d", &n, &v);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a1[i], &a2[i]);
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= v; j++) {
f[i][j] = f[i - 1][j];
if (j >= a1[i])
f[i][j] = max(f[i - 1][j], f[i][j - a1[i]] + a2[i]);
}
}
printf("%d\n", f[n][v]);
return 0;
}
完全背包优化成一维数组
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 1e3 + 5;
int f[N];
int a1[N];
int a2[N];
int main() {
int n, v;
scanf("%d%d", &n, &v);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a1[i], &a2[i]);
}
for (int i = 1; i <= n; i++) {
for (int j = a1[i]; j <= v; j++) {
f[j] = max(f[j], f[j - a1[i]] + a2[i]);
//printf("%d ", f[j]);
}
//printf("\n");
}
printf("%d\n", f[v]);
return 0;
}
多重背包
多重背包(Multiple Knapsack Problem)是背包问题(Knapsack Problem)的一个变体,它是一个经典的组合优化问题。在多重背包问题中,您有一组物品,每个物品都有一个重量、一个价值和一个可用数量限制。您需要在给定一个背包容量的情况下,选择物品以最大化总价值。
与普通背包问题不同,多重背包问题允许您选择多个相同类型的物品,而不仅仅是一个。这意味着您可以在背包中放置多个相同种类的物品,但受到每种物品数量的限制。
基础版
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
typedef long long LL;
const int N = 105, V = 105;
int arr[N], brr[N], krr[N],f[N][N];
int n, v;
int main() {
cin >> n >> v;
for (int i = 1; i <= n; i++) {
cin >> arr[i] >> brr[i] >> krr[i];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= v; j++) {
f[i][j]=f[i-1][j];
for (int k = 1; k <= krr[i]; k++) {
if(k*arr[i]<=j)
f[i][j] = max(f[i][j], f[i - 1][j - k * arr[i]] + k * brr[i]);
}
}
}
cout << f[n][v] << endl;
return 0;
}
优化版(二进制优化)
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 5;
int V[N],W[N],f[N];
int n, m;
int main() {
scanf("%d%d", &n, &m);
int cnt = 1;
for (int i = 1, v, w, s; i <= n; i++) {
scanf("%d%d%d", &v, &w, &s);
int k = 1;
while (k <= s) {
V[cnt] = v * k;
W[cnt] = w * k;
cnt++;
s -= k;
k *= 2;
}
if (s > 0) {
V[cnt] = v * s;
W[cnt] = w * s;
cnt++;
}
}
n = cnt-1;
for (int i = 1; i <= n; i++) {
for (int j = m; j >= V[i]; j--) {
f[j] = max(f[j], f[j - V[i]] + W[i]);
}
}
printf("%d\n", f[m]);
return 0;
}
分组背包
所谓分组背包,即在选择物品的时候,一开始将物品分为好几组,在选择时,可以从每一组中至多选择一件物品,问如何获得最大的价值,所以我们每次可以枚举这个组数,用i表示第几组,用j表示体积,用k来表示选择的物品,伪代码如下
for (int i = 0到组数)
for (int j = max_v到0)
for (int k = 此组所有物品)
f[j] = max (f[j], f[j - v[k]] + w[k])
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 5e2 + 5;
int V[N][N], W[N][N], S[N];
int f[N];
int n, m;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &S[i]);
for (int j = 1; j <= S[i]; j++) {
scanf("%d%d", &V[i][j], &W[i][j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = m; j >= 0; j--) {
for (int k = 1; k <= S[i]; k++) {
if (V[i][k] <= j) {
f[j] = max(f[j], f[j - V[i][k]] + W[i][k]);
}
}
}
}
cout << f[m] << endl;
return 0;
}
混合背包
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 1e3 + 5;
int f[N];
typedef struct st {
int s, v, w;
}st;
vector<st>p;
int n, m;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
int s, v, w;
scanf("%d%d%d", &v, &w, &s);
if (s < 0)
p.push_back({ -1,v,w });
else if (s == 0) {
p.push_back({ 0,v,w });
}
else {
for (int k = 1; k <= s; k*=2) {
p.push_back({ -1,v * k,w * k });
s -= k;
}
if (s > 0) {
p.push_back({ -1,s * v,s * w });
}
}
}
for (int i = 1; i <= p.size(); i++) {
if (p[i - 1].s < 0) {
for (int j = m; j >=p[i-1].v; j--) {
f[j] = max(f[j], f[j - p[i - 1].v] + p[i - 1].w);
}
}
else {
for (int j =p[i-1].v; j <= m; j++) {
f[j] = max(f[j], f[j - p[i - 1].v] + p[i - 1].w);
}
}
}
printf("%d\n", f[m]);
return 0;
}