1、二维数组构建01背包(不推荐)
例题
题解
#include <iostream>
using namespace std;
int packet[101][1010] = { 0 };
int t[101] = { 0 };
int w[101] = { 0 };
int main() {
int T, M;
cin >> T >> M;
int a, b;
for (int i = 1; i <= M; i++) {
cin >> a >> b;
t[i] = a;
w[i] = b;
}
for (int n = 1; n <= M; n++) {
for (int ti = 1; ti <= T; ti++) {
if (t[n] > ti) {
packet[n][ti] = packet[n-1][ti];
}
else {
int value1 = packet[n-1][ti-t[n]] + w[n];
int value2 = packet[n-1][ti];
if (value1 > value2) {
packet[n][ti] = value1;
}
else {
packet[n][ti] = value2;
}
}
}
}
cout << packet[M][T] ;
return 0;
}
2、一维数组构建01背包
例题
题目翻译
Bessie 去了商场的珠宝店,发现了一个手链。 当然,她想用 N (1 ≤ N ≤ 3,402) 个可用护符中最好的护符来填充它。 提供的列表中的每个魅力 i 都有一个权重 Wi (1 ≤ Wi ≤ 400),一个“合意性”因子 Di (1 ≤ Di ≤ 100),并且最多可以使用一次。 Bessie 只能支撑重量不超过 M(1 ≤ M ≤ 12,880)的吊饰手链。
将权重限制作为约束条件以及魅力列表及其权重和合意性评级,推导出最大可能的评级总和。
输入
* 第 1 行:两个空格分隔的整数:N 和 M
* 第 2..N+1 行:第 i+1 行用两个空格分隔的整数描述魅力 i:Wi 和 Di
输出
* 第 1 行:单个整数,是在给定权重限制的情况下可以实现的魅力愿望的最大总和
样本输入
4 6
1 4
2 6
3 12
2 7
样本输出
23
题解
由于本题数据较大,用二维数组会造成内存溢出,故使用一维数组 同时也推荐解题使用一维数组,二维数组只是便于理解,而一维数组相当于二维数组的某一行
本题状态转移方程为:
dp[j] = max(dp[j], dp[j - m[i]] + w[i])
#include <iostream>
#include <algorithm>
using namespace std;
int m[3403] = { 0 }, w[3403] = { 0 };
int dp[12881] = { 0 };
int main() {
int N, M;
cin >> N >> M;
int a, b;
for (int i = 1; i <= N; i++) {
cin >> a >> b;
m[i] = a; w[i] = b;
}
for (int i = 1; i <= N; i++) {
for (int j = M; j >= m[i]; j--) {
dp[j] = max(dp[j], dp[j - m[i]] + w[i]);
}
}
cout << dp[M];
return 0;
}
3、多重背包
例题
题解
本题属于二重完全背包,需构建二维数组,实质上在处理上就是比一维数组多了一个 for 循环 本题状态转移方程为:
dp[h][j] = max(dp[h][j], dp[h - 1][j - w[i]] + v[i])
#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int dp[110][110];
int v[110], w[110];
int main() {
int n, m, k, s;
while (cin >> n >> m >> k >> s) {
for (int i = 1; i <= k; i++) {
scanf("%d%d", &v[i], &w[i]);
}
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= k; i++) {
for (int j = w[i]; j <= m; j++) {
for (int h = 1; h <= s; h++) {
dp[h][j] = max(dp[h][j], dp[h - 1][j - w[i]] + v[i]);
}
}
}
if (dp[s][m] >= n) {
for (int i = 1; i <= m; i++) {
if (dp[s][i] >= n) {
printf("%d\n", m - i);
break;
}
}
}
else
printf("-1\n");
}
return 0;
}
|