Peter算法小课堂—DP背包问题

本文介绍了动态规划在01背包和完全背包问题中的应用,包括状态定义、状态转移方程,以及两种背包问题的解决方案。通过实例展示了如何使用编程方法解决此类问题。

大家好,我是Peter,我又来啦🎈🎄✨

🎈🧨🎉《动态规划》专栏来啦,目前为止,此专栏已经有四篇文章啦🎁🎀🎄

1.DP概念与编程方法    DP概念和编程方法-优快云博客

2.Peter算法小课堂—经典线性DP问题(上)Peter算法小课堂—经典线性DP问题(上)-优快云博客

3.Peter算法小课堂—经典线性DP问题(下)Peter算法小课堂—经典线性DP问题(下)-优快云博客

4.Peter算法小课堂—DP的应用    Peter算法小课堂—DP的应用-优快云博客

01背包

题目:小偷来你家,他带的包只能装c斤的财务。你家有n种财务,分别重w1、w2......wn斤,价值分别为v1、v2......,请输出能拿走的最大总价值?

状态定义

f[i][j]:用前i个物品,每个物品只能选或不选,满足重量和小于等于j的所有选法中,价值最高的那个方案

答案:f[n][c]

状态转移方程

首先,我们分两种情况讨论:1.选i   2.不选i

1。 此时我们重量和会变小w[i],但是价值会增加v[i],f[i][j]=f[i-1][j-w[i]]+v[i]

2。 此时物品数减1,f[i][j]=f[i-1][j]

最后,再取最大值,得到状态转移方程:f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i])

代码

for(int i=1;i<=n;i++) cin>>w[i]>>v[i];
for(int i=1;i<=n;++i){
	for(int j=1;j<=c;++j){
		if(w[i]>j) f[i][j]=f[i-1][j];
		else f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
	}
}
cout<<f[n][c]<<endl;

咱再来开个滚动哈,这题完美解决

for(int i=1;i<=n;i++) cin>>w[i]>>v[i];
for(int i=1;i<=n;++i){
	for(int j=c;j>=1;--j){
		f[j]=max(f[j],f[j-w[i]]+v[i]);
	}
}
cout<<f[c]<<endl;

我们看到,这个for循环里的i出现了2次,因此我们可以把w[i]写成w、v[i]写成v,这题再次完美解决

#include <bits/stdc++.h>
using namespace std;
const int MAXC=2009;
int n,c,w,v,f[MAXC];
int main(){
	cin>>c>>n;
	for(int i=1;i<=n;i++){
		cin>>w>>v;
		for(int j=c;j>=w;j--)
			f[j]=max(f[j],f[j-w]+v);
	}
	cout<<f[c]<<endl;
	return 0;
}

 完全背包

题目:小偷来你家,他带的包只能装c斤的财务。你家有n种财务,每种数量无限多,分别重w1、w2......wn斤,价值分别为v1、v2......,请输出能拿走的最大总价值?

状态定义

f[i][j]:前i种物品,每个物品可以选0、1、2......,满足重量和小于等于j的所有选法中,价值最高为多少?

答案:f[n][c]

代码

cin>>c>>n;
for(int i=1;i<=n;i++){
	cin>>w>>v;
	for(int j=w;j<=c;j++)
		f[j]=max(f[j],f[j-w]+v);
}
cout<<f[c]<<endl;

具体原因自行思考

希望这些对大家有帮助,粉丝破20更哦💟

评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值