dp背包练习
背包问题
特点:码量较少(目前只有一题超过1KB)且难度较低(实际难度橙黄绿左右),让新手也可以享受切题的快乐。
没学过背包问题的可以去看看洛谷日报中的背包问题或者背包九讲。
1.精卫填海
01背包
把物品体积当作价值,体力当做花费
最后遍历一遍dp找到体积满足要求的花费体力最小值

#include <iostream> #include <cstring> using namespace std; int m,n,c; int v[10010],w[10010]; int dp[10010]; int main() { cin>>m>>n>>c; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) for(int j=c;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); for(int i=1;i<=c;i++) if(dp[i]>=m){ cout<<c-i; return 0; } cout<<"Impossible"; return 0; }
2.[USACO09OCT]Bessie's Weight Problem G
01背包变形,类似于装箱问题
考虑到本题每个物体的价值就是体积
所以只要把模板中的价格改为体积即可

#include <iostream> using namespace std; int m,n,v[11000],ans,dp[11000]; int main() { cin>>m>>n; for(int i=1;i<=n;i++) cin>>v[i]; for(int i=1;i<=n;i++) for(int j=m;j>=v[i];j--) dp[j]=max(dp[j],dp[j-v[i]]+v[i]); cout<<dp[m]; return 0; }
3.最大约数和
01背包变形
先预处理出a放入每个数字的因数和
再用a数组进行背包,每个数字花费为1,价值为a[i]

#include <iostream> using namespace std; int a[1010],n,dp[1010]; void init() { for(int i=1;i<=1000;i++) for(int j=1;j<=i/2;j++) if(i%j==0) a[i]+=j; } int main() { cin>>n; init(); for(int i=1;i<=n;i++) for(int j=n;j>=i;j--) dp[j]=max(dp[j],dp[j-i]+a[i]); cout<<dp[n]; return 0; }
4.小书童——刷题大军
01背包变形
对于写作业使用01背包,时间为花费,分数为价值,找出能及格的花费时间最小值
刷题时间用贪心,优先选择时间少的题目

#include <iostream> #include <algorithm> using namespace std; int n,m,r,k; int a[110],v[110],w[110],st,ans; int dp[110],dp2[110]; int main() { cin>>n>>m>>k>>r; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++) cin>>w[i]; for(int i=1;i<=n;i++) cin>>v[i]; for(int i=1;i<=m;i++) for(int j=r;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); for(int i=1;i<=r;i++) if(dp[i]>=k){ st=r-i; break; } sort(a+1,a+1+n); for(int i=1;i<=n;i++){ st-=a[i]; if(st<0) break; ans++; } cout<<ans; return 0; }
5.[USACO2.2]集合 Subset Sums
01背包变形
如果n为奇数,则输出0
否则用01背包,

#include <iostream> using namespace std; long long n,dp[2500],sum; int main() { cin>>n; dp[0]=1; sum=n*(n+1)/2; if(sum%2==1){ cout<<"0"; return 0; } for(int i=1;i<=n;i++) for(int j=sum;j>=i;j--) dp[j]=dp[j]+dp[j-i]; cout<<dp[sum/2]/2; return 0; }
6.yyy2015c01 的 U 盘
二分+01背包
先二分出接口大小
再算此时最大价值是否满足条件

#include <iostream> #include <cstring> using namespace std; int n,p,s,w[1010],v[1010],dp[1010],ans; bool check(int x) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=s;j>=w[i];j--) if(w[i]<=x) dp[j]=max(dp[j],dp[j-w[i]]+v[i]); return dp[s]>=p; } int main() { int l=1,r=1,mid; cin>>n>>p>>s; for(int i=1;i<=n;i++){ cin>>w[i]>>v[i]; r=max(r,w[i]); } while(l<=r){ mid=l+r>>1; if(check(mid)){ ans=mid; r=mid-1; } else l=mid+1; } if(ans==0) cout<<"No Solution!"; else cout<<ans; return 0; }
7.Shaass and Bookshelf
01背包变形
以
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)