国王的金矿:01背包问题 动态规划解法

国王的金矿: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[maxlen];	// 开第i座矿需要的人数 

// dp[i][j]表示使用 j 个人开采 1~i 座金矿的最大收益
int dp[maxlen][max_usable];

int main()
{
	cin>>n>>usable;
	
	for(int i=1; i<=n; i++)
	{
		cin>>value[i]>>cost[i];
	}
	
	// 初始化全为0 
	for(int i=1; i<=n; i++)
	{
		for(int j=0; j<=usable; j++)
		{
			dp[i][j] = 0;
		}
	}
	
	// 计算不同人数的状况下,只开采第一座金矿的最大收益 
	for(int i=0; i<=usable; i++)
	{
		if(i >= cost[1])
		{
			dp[1][i] = value[1];
		}
	}
	
	// 从前2座到前n座金矿,逐步推导出答案 
	for(int i=2; i<=n; i++)
	{
		// j 代表使用的人手数目 
		for(int j=0; j<=usable; j++)
		{
			// 如果当前人数够开第 i 座矿 
			if(j >= cost[i])
			{
				// 对于第i座金矿,比较 开/不开 两种情况下的收益 
				int select = dp[i-1][j-cost[i]] + value[i];
				int no_select = dp[i-1][j];
				dp[i][j] = max(select, no_select);
			}
			// 人数不够,只能放弃 
			else
			{
				dp[i][j] = dp[i-1][j];
			}
		} 
	}
	
	// 打印结果 
	cout<<"//-------------------------------------//"<<endl;
	for(int i=1; i<=n; i++)
	{
		for(int j=0; j<=usable; j++)
		{
			cout<<dp[i][j]<<" ";
		}
		cout<<endl;
	}
	cout<<"//-------------------------------------//"<<endl;
	
	cout<<dp[n][usable]<<endl;
	
	return 0;
}

结果

(打印出dp数组,为了方便理解)
(第 i 行第 j 列就是使用 j 人开采前 i 座矿的最大收益)
在这里插入图片描述

发布了38 篇原创文章 · 获赞 1 · 访问量 486

猜你喜欢

转载自blog.csdn.net/weixin_44176696/article/details/104063272