01背包及优化(详细思路+代码)

初学算法的我
今天差不多看了一个半小时01背包,终于研究明白了。
赶紧记录下来,日后忘了还能捡回来!

首先说为什么叫01背包,我理解为0指没有,1指有,所以01背包问题就是是否要取这一件物品。
假设有n件物品要装进最大能装w的背包里,然后每件物品对应一个价值value和重量weigth。
然后要求的是如何装才能使装的物品的价值最大。

思路如下:
1.如果给定了几件物品,那么背包的w越大,能够装的东西就越大,价值也就越大
2.如果背包的容量一定了,那么能够装下的物品的价值越大,总价值就会越大
3.所以这个总价值由两个因素决定,背包的容量和物品的价值。
4.然后可以把问题转化成背包的容量从0到最大的时候装或不装第i件物品
下面给出一个状态转移方程:
F[i][j]=max(F[i][j],F[i-1][j-weigth[i]]+value[i])
然后结合代码和上面的思路,我想你应该就明白了。

using namespace std;
int n,m,weigth,value,f[21][501];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>value>>weigth;
		for(int j=0;j<=m;j++)
		{
			if(j>=weigth)	f[i][j]=max(f[i-1][j],f[i-1][j-weigth]+value);
			else	f[i][j]=f[i-1][j];
		}
	}
	cout<<f[n][m];
}

用一维数组优化后:

using namespace std;
int n,m,weigth,value,f[501];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>value>>weigth;
		for(int j=m;j>=0;j--)
			if(j>=weigth)	
				f[j]=max(f[j],f[j-weigth]+value);
	}
	cout<<f[m];
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
动态规划是一种解决多阶段决策过程最优化问题的数学方法。而01背包问题是动态规划中的一个经典问题,它的解题思路如下: 1.问题抽象化:将问题抽象成一个背包装物品的问题,背包有一定的容量,物品有一定的体积和价值。 2.建立模型:用一个二维数组dp[i][j]表示前i个物品放入容量为j的背包中所能获得的最大价值。 3.寻找约束条件:对于每个物品,可以选择放入背包或不放入背包,因此需要判断当前物品是否放入背包中。 4.判断是否满足最优性原理:在每个阶段,都需要选择当前状态下的最优解,以保证最终得到的解是全局最优解。 5.找大问题与小问题的递推关系式:对于每个物品,可以选择放入背包或不放入背包,因此可以得到递推公式:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]),其中w[i]表示第i个物品的体积,v[i]表示第i个物品的价值。 6.填表:按照递推公式填写二维数组dp。 7.寻找解组成:最终的解为dp[n][m],其中n表示物品的数量,m表示背包的容量。可以通过回溯得到具体的解组成。 下面是Python代码实现,其中w和v分别表示物品的体积和价值,m表示背包的容量: ```python def knapsack(w, v, m): n = len(w) dp = [[0] * (m+1) for _ in range(n+1)] for i in range(1, n+1): for j in range(1, m+1): if j < w[i-1]: dp[i][j] = dp[i-1][j] else: dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1]] + v[i-1]) res = dp[n][m] items = [] j = m for i in range(n, 0, -1): if res <= 0: break if res == dp[i-1][j]: continue else: items.append(i-1) res -= v[i-1] j -= w[i-1] return items[::-1] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给个选择

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值