有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
typedef int* intp;
typedef int** intpp;
using namespace std;
intpp record;
int n;//物品数量
int bag_size;//背包容量
intp weight;//物品重量的数组
intp value;//物品价值的数组
//递归(index:物品编号, W:背包负重)
int dfs(int index, int W) {
if (index == n || W <= 0) {
return 0;
}
//不选当前物品
int v2 = dfs(index + 1, W);
//选择当前下标的物品
if (W >= weight[index]) {
int v1 = value[index] + dfs(index + 1, W - weight[index]);
return max(v1, v2);
}
else {
return v2;
}
}
//优化递归(记录)
int dfs_2(int index, int W) {
if (index == n || W <= 0) {
return 0;
}
//计算前查找
if (record[index][W] >= 0) {
return record[index][W];
}
int res;
//不选当前物品
int v2 = dfs_2(index + 1, W);
//选择当前下标的物品
if (W >= weight[index]) {
int v1 = value[index] + dfs_2(index + 1, W - weight[index]);
res = max(v1, v2);
}
else {
res = v2;
}
//返回前保存
record[index][W] = res;
return res;
}
//动规解法
int dp() {
intpp arr_dp = new intp[n];
for (int i = 0; i < n; i++) {
arr_dp[i] = new int[bag_size + 1];
}
//初始化dp表的第一行
for (int row = 0; row < bag_size + 1; row++) {
if (row >= weight[0]) {
arr_dp[0][row] = value[0];
}
else {
arr_dp[0][row] = 0;
}
}
//其他行
for (int i = 1; i < n; i++) {
for (int j = 0; j < bag_size + 1; j++){
if (j >= weight[i]) {
int v1 = value[i] + arr_dp[i - 1][j - weight[i]];//选择当前物品
int v2 = arr_dp[i - 1][j];//不选当前物品
arr_dp[i][j] = max(v1, v2);
}
else {
arr_dp[i][j] = arr_dp[i - 1][j];
}
}
}
return arr_dp[n - 1][bag_size];
}
int main() {
//输入
cin >> n >> bag_size;
weight = new int[n];
value = new int[n];
for (int i = 0; i < n; i++){
cin >> weight[i];
}
for (int i = 0; i < n; i++) {
cin >> value[i];
}
record = new int* [n];
for (int i = 0; i < n; i++) {
record[i] = new int[bag_size + 1];
memset(record[i], -1, (bag_size + 1) * sizeof(int));
}
cout << dfs(0, bag_size) << endl;
cout << dfs_2(0, bag_size) << endl;
cout << dp() << endl;
return 0;
}
/*
测试用例:
4 5
2 1 3 2
3 2 4 2
*/