国王的金矿:动态规划中 “01背包问题” 的空间优化

国王的金矿:动态规划中 “01背包问题” 的空间优化

上一篇:国王的金矿 经典解法,使用二维数组
https://blog.csdn.net/weixin_44176696/article/details/104063272

观察经典状态转移方程

根据刻在DNA里的状态转移方程:

// cost[x] / value[x] 表示开第x座矿的需要的人手,价值
dp[i][j] = max(dp[i-1][j], dp[i-1][j-cost[i]]+value[i]);

在更新第 i 行(即求取使用 0~全部人 开采前 i 座金矿的最大收益)的时候发现

  • 第 i 行的更新,只用到了第 i-1 行保存的计算结果
  • 第 i 行 第 j 列的更新,只用到 第 i-1 行的前 j 列保存的结果

空间优化

由于第 i 行 第 j 列的更新,只用到 第 i-1 行的前 j 列保存的结果

在这里插入图片描述

我们可以 “倒着看”,来更新dp数组

  • dp数组是一维数组
  • 在第 i 次的主循环的更新中(即求取使用 0~全部人 开采前 i 座金矿的最大收益),dp[j] 表示: 使用 j 人开采 [ 前 i-1 ] 座金矿的最大收益 ,也就是前一次主循环更新的结果

故可以得到状态转移方程为:

dp[j](新)= max(dp[j](旧), dp[j-cost[i]]+value[i]);

故有更新后dp[x]表示用 x 人开采前 i 座矿的最大收益

代码

注释详细 ↓

#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座矿需要的人数 

// 第 i 次的主循环中的 dp[j]表示: 
// 使用j人开采 [前i-1] 座金矿的最大收益 
int dp[max_usable];

int main()
{
	cin>>n>>usable;
	
	for(int i=1; i<=n; i++)
	{
		cin>>value[i]>>cost[i];
	}
	
	// 初始化:计算只开采第一座矿的情况 
	for(int j=0; j<=usable; j++)
	{
		if(j >= cost[1])
		{
			dp[j] = value[1];
		}
		else
		{
			dp[j] = 0;
		}
	} 
	
	// 主循环 
	for(int i=2; i<=n; i++)
	{
		// 为了用上上一次主循环保存的值,应该倒着算 
		for(int j=usable; j>=1; j--)
		{
			// 如果人手足够 
			if(j >= cost[i])
			{
				//此时dp[x]保存的是上一次主循环的结果
				// 即 用 x 人开采前 i-1 座矿的最大收益 
				int select = dp[j-cost[i]] + value[i];
				int no_select = dp[j];	
				
				// 更新后dp[x]表示用 x 人开采前 i 座矿的最大收益 
				dp[j] = max(select, no_select);
			}
			// 如果人手不够,就不更新,值等于前 i-1 座矿的最大收益
		}
	}
	
	// 打印最终的dp数组
	cout<<"//-------------------------------------//"<<endl;
	for(int j=0; j<=usable; j++)
	{
		cout<<dp[j]<<" ";
	}
	cout<<endl<<"//-------------------------------------//"<<endl;
	
	cout<<dp[usable]<<endl;
	
	return 0;
}

运行结果

在这里插入图片描述

这种优化对于一些可用资源(即背包最大容量)可变的题目的优化是非常大的,例如有 n 个物品,所有物品最大价值之和为 m,有k种可变的最大资源(即背包最大容量)
经典dp空间复杂度:n * m * k
优化后:m * k

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

猜你喜欢

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