解法一:二维数组背包
这里注意选择之前需要测一测有没有选择的资格
#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];
}