问题
传送门: Knapsack Problem
描述
你有N种物品想要放到一个背包里面去, 物品(i)有它的价值(v_{i})和重量(w_{i})
你想要找到满足下面条件的物品:
- 物品总价值尽可能的大
- 所有物品的总重量不超过(W), 即背包的最大容量
- 每一种物品你可以选取多次
找到背包里物品的最大价值
输入
(N) (W)
(v_{1}) (w_{1})
(v_{2}) (w_{2})
(.)
(.)
(v_{N}) (w_{N})
第一行包含两个整数(N)和(W), 接下来的每一行, 给出第(i)种物品的价值和重量
输出
在一行内输出最大价值
样例输入1
4 8
4 2
5 2
2 1
8 3
样例输出1
21
样例输入2
2 20
5 9
4 10
样例输出2
10
样例输入3
3 9
2 1
3 1
5 2
样例输出3
27
求解
分析
背包问题, 参见公式(来源: 维基百科 - 无界背包问题)
dp[x]: 表示总重量不超过x的前提下, 总价值能到达的最大值
显然, dp[x] 满足:
dp[0] = 0
dp[x] = max {dp[x - 1], {v[i] + dp[x - w[i]] | w[i] < x}}
设计
w[i]: 存储重量
v[i]: 存储价值
dp[i]: 总重量不超过i时的最大价值
按照分析的公式, 使用动态规划的方法求解
编码
#include <bits/stdc++.h>
using namespace std;
#define MAX_N 105
#define MAX_W 10005
int main(void) {
int dp[MAX_W], v[MAX_N], w[MAX_N];
int N, W;
cin >> N >> W;
for (int i = 0; i < N; i++) {
cin >> v[i] >> w[i];
}
dp[0] = 0;
for (int j = 1; j <= W; j++) {
dp[j] = dp[j - 1];
for (int i = 0; i < N; i++) {
if (w[i] <= j) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
}
cout << dp[W] << endl;
}
结果
总结
...