01背包与完全背包的重新总结(dp深入学习后按自己的理解打出背包问题新算法)
//自己独创的完全背包,实际是01背包从前往后推的情况 (与3对照更好理解) #include <iostream> #include <cstdio> #include <algorithm> using namespace std; #define maxn 100010 int c[maxn],v[maxn],f[maxn]; int main(){ ios::sync_with_stdio(false); int n,m,maxx=0; cin>>n>>m; for(int i=1;i<=n;i++) cin>>c[i]>>v[i]; for(int j=1;j<=m;j++) for(int i=1;i<=n;i++) if(j-c[i]>=0) f[j]=max(f[j],f[j-c[i]]+v[i]); cout<<f[m]; } //其他人的完全背包 ,另一种从前往后推 #include <iostream> #include <algorithm> using namespace std; const int maxn=300001; int f[maxn],w[maxn],c[maxn]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>m>>n; for(int i=1;i<=n;i++) cin>>w[i]>>c[i]; for(int i=1;i<=n;i++) for(int j=w[i];j<=m;j++) f[j]=max(f[j],f[j-w[i]]+c[i]); cout<<f[m]; } //无可挑剔的01背包 #include <iostream> #include <algorithm> using namespace std; const int maxn=300001; int f[maxn],w[maxn],c[maxn]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>w[i]>>c[i]; for(int i=1;i<=n;i++)//保证每个物品只放一次 for(int j=m;j>=w[i];j--) f[j]=max(f[j],f[j-w[i]]+c[i]);//除了初次更新外,状态量必须有一个已经被更新过 cout<<f[m]; } 3 10 8 5 3 4 6 3 //理想下的推导方式 #include <iostream> #include <algorithm> using namespace std; const int maxn=300001; int f[maxn],w[maxn],c[maxn]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>w[i]>>c[i]; for(int j=1;j<=m;j++)//imaginative for(int i=minn;i<=maxn;i+=x) f[j]=max(f[j],f[j-c[i]]+v[i]); } //发现从前往后推时,可以成立如第一份代码,但无法保证物品被取至多一次 //但是要满足子问题重叠(有一个状态量已被更新过),肯定有两种思路,从后往前或从前往后 //所以此时实验从后往前推