动态规划(二)——背包dp
01背包问题(每个物品最多选一次)
AcWing 2. 0/1背包问题
朴素の版本:
#include <bits/stdc++.h> using namespace std; const int N=1010; int vi[N],wi[N],f[N][N]; int n,v; int main(){ scanf("%d%d",&n,&v); for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]); for(int i=1;i<=n;i++){ for(int j=0;j<=v;j++){ f[i][j]=f[i-1][j]; if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-vi[i]]+wi[i]); } } printf("%d",f[n][v]); return 0; }
滚动数组优化の版本:
#include <bits/stdc++.h> using namespace std; const int N=1010; int vi[N],wi[N],f[N][N]; int n,v; int main(){ scanf("%d%d",&n,&v); for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]); for(int i=1;i<=n;i++){ for(int j=0;j<=v;j++){ f[i&1][j]=f[(i-1)&1][j]; if(j>=v[i]) f[i&1][j]=max(f[i&1][j],f[(i-1)&1][j-vi[i]]+wi[i]); } } printf("%d",f[n&1][v]); return 0; }
有不了解滚动数组的读者,可以参考以下大佬博客:
https://www.cnblogs.com/kimsimple/p/6883871.html
终极优化の版本:(二维变一维)
#include <bits/stdc++.h> using namespace std; const int N=1010; int vi[N],wi[N],f[N]; int n,v; int main(){ scanf("%d%d",&n,&v); for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]); for(int i=1; i<=n; i++){ for(int j=v; j>=vi[i]; j--){ f[j]=max(f[j],f[j-vi[i]]+wi[i]); } } printf("%d", f[v]); return 0; }
完全背包问题(每个物品可以选无限多次)
AcWing 3. 完全背包问题
朴素の版本:
#include <bits/stdc++.h> using namespace std; const int N = 1010; int vi[N],wi[N],f[N][N]; int n,v; int main(){ scanf("%d%d",&n,&v); for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]); for(int i=1;i<=n;i++){ for(int j=0;j<=v;j++){ for(int k=0;k*vi[i]<=j;k++){ f[i][j]=max(f[i][j],f[i-1][j-k*vi[i]]+k*wi[i]); } } } printf("%d", f[n][v]); return 0; }
二维数组の版本:
二维数组优化の版本:
#include <bits/stdc++.h> using namespace std; const int N=1010; int vi[N],wi[N],f[N][N]; int n,v; int main(){ scanf("%d%d",&n,&v); for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]); for(int i=1;i<=n;i++){ for(int j=0;j<=v;j++){ f[i][j]=f[i-1][j]; if(j>=vi[i]) f[i][j]=max(f[i][j],f[i][j-vi[i]]+wi[i]); } } printf("%d",f[n][v]); return 0; }
终极优化の版本:
#include <bits/stdc++.h> using namespace std; const int N=1010; int vi[N],wi[N],f[N]; int n,v; int main(){ scanf("%d%d",&n,&v); for(int i=1;i<=n;i++) scanf("%d%d",&vi[i],&wi[i]); for(int i=1;i<=n;i++){ for(int j=vi[i];j<=v;j++){ f[j]=max(f[j],f[j-vi[i]]+wi[i]); } } printf("%d",f[v]); return 0; }
多重背包问题(有限次地选每件物品)---二进制优化版本
多重背包问题
二进制拆分の版本:
#include <bits/stdc++.h> using namespace std; const int N=15000; const int M=2010; int n,m,cnt; int f[M]; int v[N],w[N],s[N]; int main(){ int vi=0,wi=0,si=0; scanf("%d%d", &n, &m); //二进制拆分 for(int i=1;i<=n;i++){ scanf("%d%d%d",&vi,&wi,&si); if(si>m/vi) si=m/vi; for(int j=1;j<=si;j<<=1){ v[++cnt]=j*vi; w[cnt]=j*wi; si-=j; } if(si>0){ v[++cnt]= si*vi; w[cnt]=si*wi; } } //0/1背包 for(int i=1;i<=cnt;i++){ for(int j=m;j>=v[i];j--){ f[j] = max(f[j],f[j-v[i]]+w[i]); } } printf("%d",f[m]); return 0; }
分组背包问题(n组,每组只能选一种并且最多选一次)
分组背包问题
朴素の版本:
#include <bits/stdc++.h> using namespace std; const int N=40; const int M=210; int n,m,t; int v[N],c[N]; int g[15][N],f[15][M]; int main(){ int x=0; scanf("%d%d%d",&m,&n,&t); for(int i=1;i<=n;i++){ scanf("%d%d%d",&v[i],&c[i],&x); g[x][++g[x][0]]=i; } for(int i=1;i<=t;i++){ for(int j=0;j<=m;j++){ f[i][j]=f[i-1][j]; for(int k=1;k<=g[i][0];k++){ if(j>=v[g[i][k]]) { x=g[i][k]; f[i][j]=max(f[i][j],f[i-1][j-v[x]]+c[x]); } } } } printf("%d",f[t][m]); return 0; for(int i=1;i<=t;i++){ for(int j=0;j<=m;j++){ f[i][j]=f[i-1][j]; for(int k=1;k<=g[i][0];k++){ if(j>=v[g[i][k]]) { x=g[i][k]; f[i][j]=max(f[i][j],f[i-1][j-v[x]]+c[x]); } } } } printf("%d",f[t][m]); return 0; }
终极优化の版本:
#include <bits/stdc++.h> using namespace std; const int N=40; const int M=210; int n,m,t; int v[N],c[N],g[15][N]; int f[M]; int main(){ int x=0; scanf("%d%d%d",&m,&n,&t); for(int i=1;i<=n;i++){ scanf("%d%d%d",&v[i],&c[i],&x); g[x][++g[x][0]]=i; } for(int i=1;i<=t;i++){ for(int j=m;j>=0;j--){ for(int k=1; k<=g[i][0]; k++){ if(j>=v[g[i][k]]) { x=g[i][k]; f[j]=max(f[j],f[j-v[x]]+c[x]); } } } } printf("%d",f[m]); return 0; for(int i=1;i<=t;i++){ for(int j=m;j>=0;j--){ for(int k=1; k<=g[i][0]; k++){ if(j>=v[g[i][k]]) { x=g[i][k]; f[j]=max(f[j],f[j-v[x]]+c[x]); } } } } printf("%d",f[m]); return 0; }
以上就是背包dp中几个类型的问题了,如有错误欢迎大家在评论区指正小蒟蒻博主的错误~
本文图片来自https://blog.csdn.net/m0_73569492/article/details/129864277 鸣谢大佬
#一名爱打篮球的oier#
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】