背包前几篇文章:
一、题目
二、分析
三、朴素版代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n,m;
int v[N][N],w[N][N],s[N];
int f[N][N];
int main(){
cin>>n>>m;
for(int i = 1;i <= n;i ++){
cin>>s[i];
for(int j = 1;j <= s[i];j ++){
cin>>v[i][j]>>w[i][j];
}
}
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= m;j ++){
for(int k = 0;k <= s[i];k ++){
if(j >= v[i][k]) f[i][j] = max(f[i][j],f[i - 1][j - v[i][k]] + w[i][k]);
//注意状态转移方程中f[i][j]代表的是不选第i组第k个物品已获取的价值
//f[i - 1][j - v[i][k]] + w[i][k]代表的是选入第i组第k个物品能获取的价值
}
}
}
cout<<f[n][m]<<endl;
return 0;
}
四、优化
优化主要体现在空间复杂度优化,这道题和01背包问题一样,每一步只需要i和i-1,于是可以参考01背包的优化思路将其优化成一维。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n,m;
int v[N][N],w[N][N],s[N];
int f[N];
int main(){
cin>>n>>m;
for(int i = 1;i <= n;i ++){
cin>>s[i];
for(int j = 1;j <= s[i];j ++){
cin>>v[i][j]>>w[i][j];
}
}
for(int i = 1;i <= n;i ++){
for(int j = m;j >= 1;j --){//注意此处得逆序
for(int k = 0;k <= s[i];k ++){
if(j >= v[i][k]){
f[j] = max(f[j],f[j - v[i][k]] + w[i][k]);
}
}
}
}
cout<<f[m]<<endl;
return 0;
}