news 2026/4/30 8:35:38

代码随想录算法训练营Day-38动态规划06 | 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包、总结

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
代码随想录算法训练营Day-38动态规划06 | 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包、总结

目录

322. 零钱兑换

动规五部曲

279.完全平方数

动规五部曲

为什么相比上一题不需要if判断

139.单词拆分

动规五部曲

多重背包

问题解释

代码的改动

总结

三种背包问题

两种递推公式

组合数与排列数


322. 零钱兑换

动规五部曲

1.dp[j]的含义是,凑齐j所用最少硬币数

2.递推公式:

如果取当前硬币i,就需要dp[j-coins[i]]个硬币数再+1;
如果不取当前硬币i(前i-1个硬币就已经凑齐j) dp[j]个硬币,二者取最小值
最终递推公式为dp[j]=min(dp[j-coins[i]]+1, dp[j])

3.初始化方式:凑齐0元需要0个硬币,所以dp[0]=0; 其余初始化为最大值,否则会无法被递推公式覆盖。

4.遍历顺序:可以重复取硬币-正序遍历背包;求的是硬币最小数,所以先物品(硬币)后背包或者先背包后物品都无所谓

class Solution { public: int coinChange(vector<int>& coins, int amount) { //dp数组:dp[j]的含义是,凑齐j所用最少硬币数 vector<int> dp(amount+1, INT_MAX); //初始化:凑齐0元需要0个硬币,并且其余可初始化为最大值,否则会无法被递推公式覆盖。 dp[0] =0; //递推公式:如果取当前硬币i,就需要dp[j-coins[i]]个硬币数再+1; //如果不取当前硬币i(前i-1个硬币就已经凑齐j) dp[j]个硬币,二者取最小值 //故最终递推公式为dp[j]=min(dp[j-coins[i]]+1, dp[j]) //遍历顺序:可以重复取硬币-正序遍历背包;硬币数和顺序无关,所以是组合数,所以先硬币后背包; for(int i=0;i<coins.size();i++){ for(int j=coins[i];j<=amount;j++){ if(dp[j-coins[i]]!=INT_MAX) dp[j]=min(dp[j-coins[i]]+1, dp[j]); } } if(dp[amount]==INT_MAX) return -1; return dp[amount]; } };

279.完全平方数

动规五部曲

1.dp[j]的含义是,dp[j]的含义是,凑齐n所用最少完全平方数

2.递推公式:

如果取当前i的平方,就需要dp[j-i*i]个完全平方数再+1;
如果不取当前i的平方(前i-1个完全平方数就已经凑齐j),则就是不更新的dp[j],二者取最小值
故最终递推公式为dp[j]=min(dp[j-coins[i]]+1, dp[j])

3.初始化方式:凑齐0需要0个完全平方数,并且其余可初始化为最大值,否则会无法被递推公式覆盖。

4.遍历顺序:可以重复取硬币-正序遍历背包;可以重复取完全平方数-正序遍历背包;求最小数,所以先物品后背包或者先背包后物品都可以;

为什么相比上一题不需要if判断

先背包后物品:遍历容量1时,只能塞下1,所以dp[1]一定是1,有了这个基础,后面再遍历的时候不需要考虑前面还没有有效值覆盖的情况从而出现INT_MAX;

先物品后背包:遍历平方数1的时候,会把所有容量用1填满,同样每个值都已经变成了有效值,不是INT_MAX了,所以可以。

注:本题一定有结果,因为1可以填任意值。

class Solution { public: int numSquares(int n) { //dp数组:dp[j]的含义是,凑齐n所用最少完全平方数 vector<int> dp(n+1, INT_MAX); //初始化:凑齐0需要0个完全平方数,并且其余可初始化为最大值,否则会无法被递推公式覆盖。 dp[0] =0; //递推公式:如果取当前i的平方,就需要dp[j-i*i]个完全平方数再+1; //如果不取当前i的平方(前i-1个完全平方数就已经凑齐j),则就是不更新的dp[j],二者取最小值 //故最终递推公式为dp[j]=min(dp[j-coins[i]]+1, dp[j]) //遍历顺序:可以重复取完全平方数-正序遍历背包;求最小数,所以先物品后背包或者先背包后物品都可以; for(int i=1;i*i<=n;i++){ for(int j=i*i;j<=n;j++){ dp[j] = min(dp[j - i * i] + 1, dp[j]); } } return dp[n]; } };

139.单词拆分

动规五部曲

1.dp[j]的含义是,dp[j]的含义是,长度为j的字符串,是否能被字典中字符串填满

2.递推公式:

如果s[j:i]这个字符子串在字典内,并且dp[j]为true,则dp[i]为true

3.初始化方式:dp[0]必须为true,否则后面全为false了;其余初始值为false,否则最后直接输出true了;

4.遍历顺序

可以重复取字符串-正序遍历背包

物品的顺序会影响dp值,所以是排列数,需要先背包后物品

注:物品是字典中的字符串,但需要先匹配上,也就是用j遍历到当前容量(字符串索引),截取i-j长度的子串,如果和字典中的某元素能对上,则为有效物品,可以进行下一步判断(判断dp[j]是否为true)

class Solution { public: bool wordBreak(string s, vector<string>& wordDict) { unordered_set<string> wordSet(wordDict.begin(), wordDict.end()); vector<bool> dp(s.size()+1, false); dp[0] = true; for(int i=1;i<=s.size();i++){ for(int j=0;j<i;j++){ string str = s.substr(j,i-j); if(wordSet.find(str)!=wordSet.end() && dp[j]) dp[i]=true; } } return dp[s.size()]; } };

多重背包

问题解释

有N种物品和一个容量为V 的背包。第i种物品最多有M[i]件可用,每件耗费的空间是C[i] ,价值是W[i] 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。

只要把每种物品的M[i]件展开,就可以转化为0-1背包问题;

代码的改动

在0-1背包的先物品后背包(倒序)的基础上,再加一层循环,意思是,对于第i种物品,求放1次、放2次、...、放M[i]次到底放多少次价值最大

for(int i = 0; i < n; i++) { // 遍历物品 for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量 // 以上为01背包,然后加一个遍历个数 //遍历放入个数时,需满足背包容量大于等于k个物品i的重量 for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数 dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]); } } }

总结

三种背包问题

0-1背包:先物品后背包+背包倒序

完全背包:先物品后背包或先背包后物品或两种都可以+背包正序

多重背包(0-1背包变种):同0-1背包

两种递推公式

最值问题(尽量装满背包情况下):

dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); //dp[j] = min(dp[j], dp[j - weight[i]] + value[i]);

最多方案数问题:

dp[j] += dp[j - weight[i]];

其实不止两种,非典型的还有单词拆分这种根据字符子串是否匹配物品加上新子串前是否为true来推出当前状态的递推方式

组合数与排列数

组合数:先物品后背包-先物品则路径固定;

排列数:先背包后物品-后物品可遍历选择最后一个位置放哪个物品;


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 8:33:23

ComfyUI-Manager:AI工作流管理的终极解决方案

ComfyUI-Manager&#xff1a;AI工作流管理的终极解决方案 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable various custom nodes …

作者头像 李华
网站建设 2026/4/30 8:32:38

压缩记忆召回系统:优化大型语言模型上下文管理

1. 项目概述&#xff1a;压缩记忆召回系统 在大型语言模型应用中&#xff0c;上下文记忆管理一直是个棘手问题。传统方案要么受限于token窗口导致历史信息丢失&#xff0c;要么因全量存储带来高昂计算成本。MyMories.mmr项目提出了一种创新解决方案——通过压缩记忆召回机制&am…

作者头像 李华
网站建设 2026/4/30 8:32:09

Cynco MCP Server:AI代理如何通过MCP协议自动化处理企业财务数据

1. 项目概述&#xff1a;当AI助手成为你的专属财务分析师如果你和我一样&#xff0c;每天要在Claude、Cursor这些AI工具里花上几个小时&#xff0c;同时还得处理公司那堆永远理不清的账目——发票、银行流水、应收应付、折旧计算——那你肯定也幻想过&#xff0c;能不能让AI直接…

作者头像 李华
网站建设 2026/4/30 8:32:03

Windows虚拟串口终极解决方案:com0com驱动完整指南

Windows虚拟串口终极解决方案&#xff1a;com0com驱动完整指南 【免费下载链接】com0com Null-modem emulator - The virtual serial port driver for Windows. Brought to you by: vfrolov [Vyacheslav Frolov](http://sourceforge.net/u/vfrolov/profile/) 项目地址: https…

作者头像 李华