[Aizu] Knapsack Problem 背包问题

问题

传送门: 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;
}

结果

总结

...

posted @ 2019-05-28 21:41  by-sknight  阅读(247)  评论(0)    收藏  举报