背包dp笔记
背包 笔记
背包是线性DP中一类重要而特殊的模型,下面分几个板块讲述。
0/1背包
给定
根据以前线性
显然,状态转移方程如下:
边界情况:
时间复杂度
关键代码如下:
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++)
f[i][j]=f[i-1][j];
for(int j=v[i];j<=m;j++)
f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
滚动数组优化:注意循环枚举的顺序
int f[MAX_M+1];
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++){
for(int j=m;j>=v[i];j--){
f[j]=max(f[j],f[j-v[i]]+w[i]]);
}
}
int ans=0;
for(int i=0;i<=m;i++)ans=max(ans,f[i]);
例题:数字组合
给定
数据范围:
这是一个典型的
核心代码如下:
int f[MAX_M+1];
memset(f,0,sizeof(f));
f[0]=1;
for(int i=1;i<=n;i++){
for(int j=m;j>=a[i];j--){
f[j]+=f[j-a[i]];
}
}
cout<<f[m]<<endl;
完全背包
完全背包问题模型如下:
给定
先来考虑使用传统的二维线性
初值:
与
int f[MAX_M+1];
memset(f,0xcf,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++)
for(int j=v[i];j<=m;j++)
f[j]=max(f[j],f[j-v[i]]+w[i]);
int ans=0;
for(int j=0;j<=m;j++)
ans=max(ans,f[j]);
例题:
给定一个自然数
这是一个典型的完全背包模型,
f[0]=1;
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
f[j]=(f[j]+f[j-i])%mod;
printf("%lld\n",f[n]%mod-1);
多重背包
多重背包问题模型如下:
给定
直接拆分法
求解多重背包问题最直接的方法就是把第
unsigned int f[MAX_M+1];
memset(f,0xcf,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=c[i];j++)
for(int k=m;k>=v[i];k--)
f[k]=max(f[k],f[k-v[i]]+w[i]);
int ans=0;
for(int i=0;i<=m;i++)ans=max(ans,f[i]);
二进制拆分法
众所周知,从
1.根据
2.从
综上所述,,我们可以把数量为
这
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现