多重背包问题入门+dp储存空间优化

博客围绕多重背包问题入门及dp储存空间优化展开,将其与洛谷通天背包问题对应。介绍了多重背包和01背包的区别,分析问题并给出AC代码。还阐述了用一维数组优化存储空间的原理,强调实现对比和覆盖过程的要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多重背包问题入门+dp储存空间优化

这个入门知识点对应洛谷通天背包问题。
下面看下问题:
在这里插入图片描述
AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int weight[2000],price[2000],s[2000][200000],number1[2000];
int dp[2000];
int main()
{
	int m,n,number=0,t=0;
	cin>>m>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>weight[i]>>price[i]>>number;
		t=max(t,number);
		number1[number]++;
		s[number][number1[number]]=i;
	}
	for(int i=1;i<=t;i++)//总共有t组 从第一组开始 
	{
		for(int j=m;j>=0;j--)//背包容积剩余 j  
		{
			for(int c=1;c<=number1[i];c++)//这组里面有多少个元素 
			{
				if(j>=weight[s[i][c]])
				{
					dp[j]=max(dp[j],dp[j-weight[s[i][c]]]+price[s[i][c]]);
				}
		    }
		}
	
	}	
	cout<<dp[m]<<endl;
	return 0;
 } 

多重背包和01背包的区别就是01背包的物体只是单个的,但多重背包问题的物品是集合的形式。打个比方:01背包面对的物品是砖石或砖头,但多重背包问题面对的物品是一个砖石和砖头混在一起的物品,如果要选择价值最大的,就要对这个混合物进行挑选。


将题目的意思转述一下:你有一个容积为V的背包,有N个箱子,每个箱子里有m件物品,现在从每个箱子里取物品,且每个箱子最多只能拿走一件物品,问你能拿走的最大价值物品为多少。
分析下问题:看到这个东西很快能想到01背包的dp,但有一处不同,即01背包中的一个物品变成了一个箱子。所以我们要在原本的模板上加一重循环,表示遍历箱子中的每一个物品。


分析一下代码:

for(int i=1;i<=t;i++)//总共有t组 从第一组开始 
	{
		for(int j=m;j>=0;j--)//背包容积剩余 j  
		{
			for(int c=1;c<=number1[i];c++)//这组里面有多少个元素 
			{
				if(j>=weight[s[i][c]])
				{
					dp[j]=max(dp[j],dp[j-weight[s[i][c]]]+price[s[i][c]]);
				}
		    }
		}
	}

和01背包相似,我们要确定当前状态的最值,即当在前 i 个箱子里取物体,背包容积为 j 时的最值。
那么我们要进行对比的是:前i-1个箱子取物体,背包容积为j时的最值。


AC代码里我是用一维数组来进行存储空间的优化的,所以就聊聊为什么可以这样写吧!
首先:不难发现,每一次比较都是通过与上一次数据进行比较,所以只用把现在的数据覆盖在原有的数据之上就可以实现二维数组的功能。
但使用这种存储空间的优化要注意:一定从j=m 开始递减,这样才可以模拟覆盖过程,实现对比功能。
上面的话要听的活一点,不要什么题都重最大开始递减,关键还是要实现对比和覆盖的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值