采药(01背包)

在这里插入图片描述
在这里插入图片描述
解法一:二维数组背包
这里注意选择之前需要测一测有没有选择的资格

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int T,M;
int f[1005][1005];
int t[1005],v[1005];
int main(){
	cin>>T>>M;
	for(int i=1;i<=M;i++) cin>>t[i]>>v[i];
	for(int i=1;i<=M;i++){
		for(int j=1;j<=T;j++){
			f[i][j]=f[i-1][j];//不选 
			if(j>=t[i]){//当前背包容量必须大于当前物体容量才可判断是否选择
				//状态转移方程 
				f[i][j]=max(f[i][j],f[i-1][j-t[i]]+v[i]);//选择 
			}
		}
	}
	/*for(int i=0;i<=M;i++){
		for(int j=0;j<=T;j++){
			cout<<f[i][j]<<" ";
		}cout<<endl;
	}*/
	cout<<f[M][T]; 
	return 0;
}

解法二:一维背包,思想和二维一样,不过一维背包的从后往前填数比较的方法非常巧妙,既不会动上一次数,又可以知己而拿来比较

 #include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int T,M;
int f[1005];//f[j]表示背包容量为j时,当前的最大价值 
int t[1005],v[1005];
int main(){
	cin>>T>>M;
	for(int i=1;i<=M;i++) cin>>t[i]>>v[i];
	
	for(int i=1;i<=M;i++){
		for(int j=T;j>=t[i];j--){//当j>=t[i]时不用考虑那么多,因为没有选择的机会,所以保留上一次数
			f[j]=max(f[j],f[j-t[i]]+v[i]);
		}
	}
	/*for(int i=0;i<=M;i++){
		for(int j=0;j<=T;j++){
			cout<<f[i][j]<<" ";
		}cout<<endl;
	}*/
	cout<<f[T]; 
	return 0;
}

优化
观察方法二可以发现,我们只需要维护当前输入的物品的价值和体积就可以,其他物品(包括前面的物品我们都不用关心),所以我们可以把数组t[],v[]用变量t,v代替,放入第一层循环内输入即可

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int T,M;
int f[1005];//f[i]表示背包容量为i时,他的最大价值 
int t,v;
int main(){
	cin>>T>>M;
	
	for(int i=1;i<=M;i++){
		cin>>t>>v;
		for(int j=T;j>=t;j--){
			f[j]=max(f[j],f[j-t]+v);
		}
	}
	/*for(int i=0;i<=M;i++){
		for(int j=0;j<=T;j++){
			cout<<f[i][j]<<" ";
		}cout<<endl;
	}*/
	cout<<f[T]; 
	return 0;
}

01背包模板:

#include<bits/stdc++.h>
using namespace std;
int m,tw,w,v,dp[1005];
/*
m:物品种类
tw:背包总容量
w:当前输入物品的重量
v:当前输入物品的价值 
dp[]:背包数组 
*/
int main(){
	cin>>tw>>m;
	for(int i=1;i<=m;i++){
		cin>>w>>v;
		for(int j=tw;j>=w;j--){
			dp[j]=max(dp[j],dp[j-w]+v);
		}
	}
	cout<<dp[tw];
} 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值