01经典背包

本文详细介绍了动态规划的概念,通过一个典型的背包问题实例,解释了如何使用动态规划解决问题。重点阐述了状态转移方程的建立过程及优化方法,包括滚动数组的应用,最终提供了高效求解背包问题的算法实现。

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

早就想好好学下dp,因为之前一直对它很敬畏,虽然对我以后的工作应该没什么用,但是感觉dp已然成为我的

一个心病了,所以趁着现在,还算比较空吧,好好学习下算法。

其实到现在我也还是不怎么明白什么状态转移,以后只能靠多做几道题目来感受了,我就先把现在所想的记下来。

有n个物品,背包容量是m,每个物品对应重量wi,价值vi,求背包在容量内所能装的最大价值。

我第一个感觉就是穷举,每个背包都有两个选择,要或者不要,那么这样的算法复杂度就是2^n。

算法书上的解法是这样的(我现在还没想好怎么想到这一步):

开一个数组value[n][m],value(i,j)表示对是否选择第i个物品做决策,使在j重量下所能达到的最大value值。

那么建立的条件就是保证上一次value(i-1,j-wi)所取得的值也是最大的,这里只需要做n次决策,遍历m的范围,

因此算法复杂度为O(nm),得到

传说中的状态转移方程 value(i,j)=max{value[i-1][j],value[i-1][j-wi]+vi}j>=wi

for(i = 0; i <= m; i++)
	value[0][i]=0;
for(i = 1; i <= n; i++)
{
	cin>>w>>v;
	for(j = 1; j <= m; j++)
	{
		if(j >= w)
			value[i][j] = value[i-1][j]>value[i-1][j-w] + v ?
			value[i-1][j] : value[i-1][j-w]+v;
		else value[i][j] = value[i-1][j];
	}
}
cout<<value[n][m]<<endl;

观察代码可知,此次的决策只与前一次有关,因此可以用滚动数组,从后往前推,这样保证了value[j]保存的是

上一次的value[j].

memset(value,0,sizeof(value));
		for(i = 1; i <= n; i++)
		{
			cin>>w>>v;
			for(j = m; j >= 0; j--)
			{
				if(j >= w)
					value[j] = value[j] > value[j-w] + v?
					value[j]:value[j-w] + v;
			}
		}
		cout<<value[m]<<endl;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值