当前位置: 首页 > article >正文

代码随想录算法训练营Day37 | 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包、背包问题总结

文章目录

  • 322.零钱兑换
    • 思路与重点
  • 279.完全平方数
    • 思路与重点
  • 139.单词拆分(二刷再看看!)
    • 思路与重点
  • 多重背包
    • 思路与重点
  • 背包问题总结


322.零钱兑换

  • 题目链接:322. 零钱兑换
  • 讲解链接:代码随想录
  • 状态:一遍AC。

思路与重点

  • 本题求钱币最小个数,那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数。所以本题的两个for循环内外层顺序也无所谓
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, INT_MAX);
        dp[0] = 0;
        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], dp[j - coins[i]] + 1);
            }
        }
        return dp[amount] < INT_MAX ? dp[amount] : -1;
    }
};

279.完全平方数

  • 题目链接:279.完全平方数
  • 讲解链接:代码随想录
  • 状态:一遍AC。

思路与重点

  • 本题和 322. 零钱兑换 基本是一样的。
class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<unsigned long long> dp(amount + 1, 0);
        dp[0] = 1;
        for(int i = 0; i < coins.size(); i++){
            for(int j = coins[i]; j <= amount; j++){
                dp[j] += dp[j - coins[i]];
            }
        }
        return dp[amount];
    }
};

139.单词拆分(二刷再看看!)

  • 题目链接:139.单词拆分
  • 讲解链接:代码随想录
  • 状态:没写出来。

思路与重点

  • 用记忆化递归解决:使用memory数组保存每次计算的以startIndex起始的计算结果,如果memory[startIndex]里已经被赋值了,直接用memory[startIndex]的结果。
class Solution {
private:
    bool backtracking (const string& s,
            const unordered_set<string>& wordSet,
            vector<bool>& memory,
            int startIndex) {
        if (startIndex >= s.size()) {
            return true;
        }
        // 如果memory[startIndex]不是初始值了,直接使用memory[startIndex]的结果
        if (!memory[startIndex]) return memory[startIndex];
        for (int i = startIndex; i < s.size(); i++) {
            string word = s.substr(startIndex, i - startIndex + 1);
            if (wordSet.find(word) != wordSet.end() && backtracking(s, wordSet, memory, i + 1)) {
                return true;
            }
        }
        memory[startIndex] = false; // 记录以startIndex开始的子串是不可以被拆分的
        return false;
    }
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
        vector<bool> memory(s.size(), 1); // -1 表示初始化状态
        return backtracking(s, wordSet, memory, 0);
    }
};
  • 完全背包的思路:
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 word = s.substr(j, i - j); //substr(起始位置,截取的个数)
                if (wordSet.find(word) != wordSet.end() && dp[j]) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.size()];
    }
};

多重背包

  • 题目链接:56. 携带矿石资源
  • 讲解链接:代码随想录
  • 状态:直接看题解了。

思路与重点

  • 多重背包和01背包是非常像的, 为什么和01背包像呢?每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。
#include<iostream>
#include<vector>
using namespace std;
int main() {
    int bagWeight,n;
    cin >> bagWeight >> n;
    vector<int> weight(n, 0);
    vector<int> value(n, 0);
    vector<int> nums(n, 0);
    for (int i = 0; i < n; i++) cin >> weight[i];
    for (int i = 0; i < n; i++) cin >> value[i];
    for (int i = 0; i < n; i++) cin >> nums[i];

    vector<int> dp(bagWeight + 1, 0);

    for(int i = 0; i < n; i++) { // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
            // 以上为01背包,然后加一个遍历个数
            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]);
            }
        }
    }

    cout << dp[bagWeight] << endl;
}

背包问题总结

  • 讲解链接:代码随想录

http://www.kler.cn/a/463837.html

相关文章:

  • 【重庆】《政务数字化应用费用测算规范》(T/CDCIDA 001—2023)-省市费用标准解读系列36
  • 非docker方式部署openwebui过程记录
  • 【pytorch】现代循环神经网络-2
  • 4.Web安全——JavaScript基础
  • nature reviews genetics | 需要更多的针对不同种族的癌症基因组图谱研究,促进精准治疗和维护治疗公平权益
  • 基本算法——回归
  • C++笔记之C语言和C++中未初始化变量的默认值问题
  • WKWebView打开pdf文件乱码?各种方案整理。
  • HTML——42.自定义列表
  • 【python】unittest单元测试
  • 家教系统|Java|SSM|VUE| 前后端分离
  • Ethernet 系列(13)-- 基础学习::VLAN
  • 019-spring-基于aop的事务控制原理
  • 【网络安全实验室】脚本关实战详情
  • 使用 MySQL 实现数据交互:从数据存储到查询优化
  • SAP学习笔记 - 豆知识14 - Msg 番号 M7562 - 取引Type WL 对应的番号範囲中不存在2025年度 OMBT
  • CSS 之 position 定位属性详解
  • 【JVM】总结篇-字节码篇
  • 诗韵--代码之外的生活:2025 元旦歌
  • Tailwind CSS 实战:社交媒体信息流开发
  • 【从零开始】11. LLaMA-Factory 微调 Qwen 模型(番外篇)
  • JVM:记录一次因为查询量过大导致的OOM问题(四)
  • 深入理解 ElasticSearch 索引与检索原理
  • Vue Prop 默认值深入解析:工厂函数与 rawProps 的正确使用
  • 多点通信、流式域套接字
  • leetcode hot 100 跳跃游戏2