算法之动态规划(DP)求解完全背包问题(状态转移式方程推导)
完全背包是01背包的进阶版。在这里补充一下代码随想录的完全背包状态转移式的推导。有兴趣的可以先看一看原版。
-
状态转移方程
状态:dp[i][j] 选择前i个物品,容量为j的背包时 所选物品价值总和最大。
状态转移:
dp[i][j]=max(dp[i-1][j-k* v[i]]+k* w[i]) (k=0,1,2,3...) (j-k* v[i]>0) -
方程优化
dp[i][j]=max(dp[i-1][j],dp[i-1][j- v[i]]+ w[i],dp[i-1][j- 2* v[i]]+ 2* w[i],....) --->(1)
dp[i][j-v[i]]=max(dp[i-1][j-v[i]],dp[i-1][j- 2* v[i]]+ w[i],dp[i-1][j- 3* v[i]]+ 2* w[i],....)
dp[i][j-v[i]]+w[i]=max(dp[i-1][j-v[i]]+w[i],dp[i-1][j- 2* v[i]]+ 2 * w[i],dp[i-1][j- 3* v[i]]+ 3* w[i],....) --->(2)
结合(1)(2)可得:
dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+w[i]); -
对比01背包
- dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i])(01背包)
- dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+w[i])(完全背包)
发现了区别在下标从i-1变为i。为什么呢?
f[i][j - v[i]] 已经将除去1个物品i时的所有最优解已经求出来了,因此在计算f[i][j]时,无需再重复计算k=2,3,4,5…时的值了。
- 代码:
// 先遍历物品,在遍历背包
void test_CompletePack() {
vector<int> weight = {1, 3, 4};
vector<int> value = {15, 20, 30};
int bagWeight = 4;
vector<int> dp(bagWeight + 1, 0);
for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = weight[i]; j <= bagWeight; j++) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
cout << dp[bagWeight] << endl;
}
int main() {
test_CompletePack();
}
Don't aim for success if you really want it.Just stick to what you love and believe in.And it will come naturally.
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 我干了两个月的大项目,开源了!
· 推荐一款非常好用的在线 SSH 管理工具
· 千万级的大表,如何做性能调优?
· 盘点!HelloGitHub 年度热门开源项目
· Phi小模型开发教程:用C#开发本地部署AI聊天工具,只需CPU,不需要GPU,3G内存就可以运行,