最近刚开始刷dp的题目,留下这篇文章以作纪念。
dp[i][j]的含义为前0~i个物品放到容量j的背包里的最大价值
首先,容量为0以及物品数量为0的情况价值必定为0
所以我们可以初始化dp数组的第一行以及第一列的值为0
dp[i][j]的可以分两种情况讨论:
1.不选择物品i,那么价值为0~i-1个物品放入容量j的背包的最大价值,即dp[i-1][j]
2.选择物品i,物品i可选择k个,k个i物品为的价值为v[i]*k,剩下的容量j-k*w[i]装入0~i-1个物品,
那么此时价值就是 v[i]*k+dp[i-1][j-k*w[i]]
我们只需取两种情况的最大值即可。
重量需排序后才能做
#include <iostream>
using namespace std;
int dp[1001][1001];//dp[i][j]表示前i个物品放到容量j的背包里的最大价值
int main() {
int N, M;
cin >> N >> M;
int W[N + 1], V[N + 1];
for (int i = 1; i <= N; i++) {
cin >> W[i] >> V[i];
}
for (int i = 0; i <= 1001; i++) {//当容量为0或个数为0时没有价值
dp[i][0] = dp[0][i] = 0;
}
for (int i = 1; i <= N - 1; i++) {//简单的冒泡排序
for (int j = 1; j <= N - i; j++) {
if (W[j] > W[j + 1]) {
int temp = W[j];
W[j] = W[j + 1];
W[j + 1] = temp;
temp = V[j];
V[j] = V[j + 1];
V[j + 1] = temp;
}
}
}
//核心代码
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
dp[i][j] = dp[i - 1][j];//不选第i个物品时
for (int k = 1; k <= j / W[i]; k++) {
int A = dp[i - 1][j - k * W[i]] + k * V[i];//选k个物品i时的价值
dp[i][j] = dp[i][j] > A ? dp[i][j] : A;
}
}
}
cout << dp[N][M];
}
如有不足,望多加以批评