【动态规划】二维的背包问题、似包非包、卡特兰数

📝前言说明:

  • 本专栏主要记录本人的动态规划算法学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing

📋本专栏:C++刷题专栏

📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux

🎀CSDN主页 愚润泽

你可以点击下方链接,进行不同专题的动态规划的学习

点击链接 开始学习
斐波那契数列模型 路径问题
简单多状态(一) 简单多状态(二)
子数组系列(一) 子数组系列(二)
子序列问题(一) 子序列问题(二)
回文串(一) 回文串(二)
两个数组dp问题(一) 两个数组的dp问题(二)
01背包问题 完全背包
二维的背包问题 其他

题单汇总链接:点击 → 题单汇总

题目

  • [474. 一和零](#474. 一和零)
  • [879. 盈利计划](#879. 盈利计划)
  • [377. 组合总和 Ⅳ(似包非包)](#377. 组合总和 Ⅳ(似包非包))
  • [96. 不同的二叉搜索树(卡特兰数)](#96. 不同的二叉搜索树(卡特兰数))

474. 一和零

题目链接:https://leetcode.cn/problems/ones-and-zeroes/description/


优质解

思路:

  • 二维费用的背包问题:要满足两个条件的背包问题
  • 状态表示:dp[i][j][k]:从前 i 个字符串里面选,0 的个数不超过 j , 1 的个数不超过 k 的子集的所有选法中,字符串最多的个数
  • 状态表示:区分 选 or 不选 第 i 个字符
  • 初始化:当 i == 0,dp的值都为 0
  • 填表顺序:i 从小到大
  • 返回值:dp[len][m][n],len为字符串长度

代码:

cpp 复制代码
class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
       int len = strs.size();
       vector<vector<vector<int>>> dp(len + 1, vector<vector<int>>(m + 1, vector<int>(n + 1, 0)));
       for(int i = 1; i <= len; i++)
       {
            int a = 0, b = 0;
            for(auto ch: strs[i - 1])
            {
                if(ch == '0') a++;
                else if(ch == '1') b++;
            }
            for(int j = 0; j <= m; j++)
            {
                for(int k = 0; k <= n; k++)
                {
                    dp[i][j][k] = dp[i - 1][j][k];
                    if(j >= a && k >= b)
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - a][k - b] + 1);
                }
            }
       }
       return dp[len][m][n];
    }
};

时间复杂度:O(len × m × n)
空间复杂度:O(len × m × n)


879. 盈利计划

题目链接:https://leetcode.cn/problems/profitable-schemes/description/


优质解

思路:

  • TODO(还没做)

代码:

cpp 复制代码
class Solution {
public:
    int profitableSchemes(int n, int m, vector<int>& g, vector<int>& p)
    {
        const int MOD = 1e9 + 7; // 注意结果取模
        int len = g.size();
        vector<vector<vector<int>>> dp(len + 1, vector<vector<int>>(n + 1, vector<int>(m + 1)));
        for(int j = 0; j <= n; j++) dp[0][j][0] = 1; // 初始化
        for(int i = 1; i <= len; i++)
            for(int j = 0; j <= n; j++)
                for(int k = 0; k <= m; k++)
                {
                    dp[i][j][k] = dp[i - 1][j][k];
                    if(j >= g[i - 1])
                        dp[i][j][k] += dp[i - 1][j - g[i - 1]][max(0, k - p[i - 1])];
                    dp[i][j][k] %= MOD; // 注意结果取模
                }
        return dp[len][n][m];
    }
};

时间复杂度:
空间复杂度:


377. 组合总和 Ⅳ(似包非包)

题目链接:https://leetcode.cn/problems/combination-sum-iv/description/


优质解

思路:

  • TODO (还没做)

代码:

cpp 复制代码
class Solution
{
public:
    int combinationSum4(vector<int>& nums, int target)
    {
        vector<double> dp(target + 1);
        dp[0] = 1;
        for(int i = 1; i <= target; i++)
            for(auto x : nums)
                if(x <= i) dp[i] += dp[i - x];
        return dp[target];
    }
};

时间复杂度:
空间复杂度:


96. 不同的二叉搜索树(卡特兰数)

题目链接:https://leetcode.cn/problems/unique-binary-search-trees/description/


优质解

思路:

  • TODO(还没做)

代码:

cpp 复制代码
class Solution
{
public:
    int numTrees(int n)
    {
        vector<int> dp(n + 1, 0); // dp[i] 表示: 当结点的数量为 i 个的时候,一共有多少颗 BST
        dp[0] = 1; // 空树也是一颗二叉搜索树
        for (int i = 1; i <= n; i++) // 枚举结点的总数
            for (int j = 1; j <= i; j++)  // 选择每一个根节点
                dp[i] += dp[j - 1] * dp[i - j]; // 二叉树总量累加在一起
        return dp[n];
    }
};

时间复杂度:
空间复杂度:


🌈我的分享也就到此结束啦🌈

要是我的分享也能对你的学习起到帮助,那简直是太酷啦!

若有不足,还请大家多多指正,我们一起学习交流!

📢公主,王子:点赞👍→收藏⭐→关注🔍

感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

相关推荐
垆边人似月.41 分钟前
华为机试题 :字符串压缩
算法·华为
ggb喔41 分钟前
52pojie 的图片工具:为什么无损转换后体积涨了 6 倍、照片方向还是歪的
图像处理·python·算法·计算机视觉·图形渲染·媒体
小小龙学IT42 分钟前
Go 语言 cgo 与 C/C++ 互操作深度解析:从 fwlib 直连到工业数采网关实战系列
c语言·c++·golang
菜鸟~noob23344 分钟前
【电子战】第25篇:自由空间、双射线与菲涅尔区【含matlab代码】
开发语言·算法·matlab
地平线开发者1 小时前
地平线征程6M YOLOv8s 部署
算法·自动驾驶
Run_Teenage1 小时前
算法:Manacher(马拉车)算法、中心扩展算法
算法
Tisfy2 小时前
LeetCode 0301.删除无效的括号:二进制枚举 / 回溯
算法·leetcode·字符串·题解·回溯·括号匹配·二进制枚举
Nil2082 小时前
leetcode 322零钱兑换
算法·leetcode·职场和发展
海绵宝宝转agent2 小时前
2026-10-9 leetcode100刷题+面经整理
笔记·算法·面试
yi0112 小时前
DAY24: LeetCode 167:两数之和 II|从暴力枚举到左右双指针
笔记·python·算法·leetcode·二分查找·双指针