算法描述
有一个容量为W的背包和n个物品,每个物品的重量为wi,价值为vi。要求选出一些物品放入背包中,使得放入的物品的总重量不超过W,且总价值最大。
题目描述
有一个容量为W的背包和n个物品,每个物品的重量为wi,价值为vi。要求选出一些物品放入背包中,使得放入的物品的总重量不超过W,且总价值最大。
解答
使用动态规划,设dp[i][j]表示前i个物品放入容量为j的背包中所能获得的最大价值,则有dp[i][j] = max(dp[i-1][j], dp[i-1][j-wi] + vi)。
代码
以下是使用C++实现0/1背包问题(解决每个物品只能使用一次的情况)的代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1000; // 最大物品数
const int MAXV = 10000; // 最大背包容量
int w[MAXN], v[MAXN]; // w存储每个物品的重量,v存储每个物品的价值
int dp[MAXN][MAXV]; // 动态规划数组
// 动态规划求解0/1背包问题
int knapsack(int n, int V) {
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= V; j++) {
if (j < w[i]) {
dp[i][j] = dp[i-1][j];
} else {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);
}
}
}
return dp[n][V];
}
int main() {
int n; // 物品数
int V; // 背包容量
cin >> n >> V;
for (int i = 1; i <= n; i++) { // 输入每个物品的重量和价值
cin >> w[i] >> v[i];
}
int ans = knapsack(n, V); // 求最大价值
cout << ans << endl;
return 0;
}
在以上代码中,我们使用一个二维数组dp来存储当前重量和当前物品数下的最大价值。首先对边界条件进行初始化,然后根据状态转移方程进行逐步求解,在每个位置上,如果当前背包容量小于第i件物品的重量,则最大价值等于去掉这件物品后的前i-1件物品的最大价值;否则,最大价值等于去掉这件物品后的前i-1件物品的最大价值和去掉前i-1件物品而多放这件物品的价值的最大值。最后返回n个物品和V个容量下的最大价值即可。