国王的金矿:01背包问题 动态规划解法
题目描述
有一个国家发现了 n 座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。
参与挖矿工人的总数是 m 人。
每座金矿要么全挖,
要么不挖,不能派出一半人挖取一半金矿。
要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?
输入输出
第一行输入两个整数 n,m表示有n座矿,m个人可用,接下来n行,每行输入两个整数value,cost,代表第 i 座金矿的价值和需要的人数
样例输入输出
sample input:
5 10
200 3
300 4
350 3
400 5
500 5
sample output:
900
思路
背包的动态规划问题的转化 ↓
人数=背包容量,金矿收益=物品价值
定义状态:dp[i][j]表示使用 j 个人开采 1~i 座金矿的最大收益
int dp[maxlen][max_usable];
将问题拆解为子问题求解:
- 先计算 0 ~ m 个人去开采第一座金矿的最大收益
- 对于第x座金矿,需要花费人手cost个以完成开采,我们有开和不开两个选项,如果当前手头上有y个人,那么开采前x座金矿的最大收益就是在【使用 y 个人开采前 x-1 座金矿】与【使用 y-cost 个人开采前 x- 1座金矿 + 使用 cost 个人开采第x座金矿】之中选一个最大的收益。
- 有了初始状态,递推式,我们就可以从x=2开始,逐步推导出x=n时的情况,也就是题目的答案
代码
#include <iostream>
using namespace std;
#define maxlen 114
#define max_usable 1145
#define max(a, b) ((a>b)? (a):(b))
int n, usable; // 矿数,可用人数
int value[maxlen]; // 第i座矿的价值
int cost