训练营刷题:《在给定预算内租用货船》 | 豆包MarsCode AI 刷题

112 阅读6分钟

学习方法与心得

我是在参加今年的字节后端训练营时首次接触到豆包MarsCode AI的。起初,我并没有太多关注编程题库的选择,但在字节的工作人员的热情推荐下,我决定试试看这个平台。当我开始使用豆包MarsCode AI时,发现它不仅仅是一个简单的刷题工具,更是一个集学习、反馈和进阶于一体的智能平台。通过这个平台,我可以在完成各类编程题目的同时,获得系统的反馈和优化建议,从而不断提升自己的编程能力。随着对平台功能的逐步了解,我逐渐意识到它能够帮助我高效地提升算法与编程技能,尤其是在进行深入学习和准备技术面试时,显得尤为重要。

1. 题目解析

为了更好地理解编程问题并提高解题能力,我选择了豆包MarsCode AI题库中的一个经典题目:在给定预算内租用货船。题目描述为:小S在码头租用货船,有 Q 种不同类型的货船可供选择。每种货船有固定的数量 m[i]、租赁成本 v[i] 和最大载货量 w[i]。小S希望在预算 V 元内,租用能够承载最大总货物的货船组合。每种货船的具体信息包括数量、租赁价格和载货量。小S需要你帮忙计算在给定预算下,她能租用的货船的最大总载货量是多少。

  • Q: 货船的种类数量。
  • V: 李华可用的总预算(单位:元)。
  • ships: 一个列表,其中每个元素是一个元组 [m[i], v[i], w[i]],分别表示第 i 种货船的数量、租赁价格和每艘货船的最大载货量。

思路解析:

这道题目本质上是0/1背包问题的变种,涉及到多重背包(可以选择每种货船的多个实例)。我们需要在预算范围内选择最优的货船组合,使得总的载货量最大。解决该问题的关键在于动态规划(DP)。

  • 定义dp[j]表示当预算为j时,能够达到的最大载货量。

  • 对于每一种货船,考虑是否选择若干艘货船,并更新dp数组。

  • 需要注意的是,在进行动态规划更新时,我们要从预算V向下遍历,以防止同一艘船被多次选择。

    public class Main {
        public static int solution(int Q, int V, List<List<Integer>> ships) {
            // dp数组存储预算j下的最大载货量
            int[] dp = new int[V + 1];
            
            // 遍历每种货船
            for (List<Integer> ship : ships) {
                int m = ship.get(0); // 货船数量
                int v = ship.get(1); // 租赁价格
                int w = ship.get(2); // 载货量
                
                // 处理每种货船的租赁
                for (int k = 1; k <= m; k++) {
                    int cost = k * v; // 租赁k艘货船的总费用
                    int weight = k * w; // 租赁k艘货船的总载货量
                    
                    // 更新dp数组,避免重复选择
                    for (int j = V; j >= cost; j--) {
                        dp[j] = Math.max(dp[j], dp[j - cost] + weight);
                    }
                    // 剩余的货船数量处理
                    m -= k;
                }
                
                // 如果还有剩余货船,直接更新
                if (m > 0) {
                    int cost = m * v;
                    int weight = m * w;
                    for (int j = V; j >= cost; j--) {
                        dp[j] = Math.max(dp[j], dp[j - cost] + weight);
                    }
                }
            }
            
            // 返回最大载货量
            return dp[V];
        }
    }
    ​
    

    思路分析:

    • dp[j]数组的初始化为0,表示预算为0时无法租船。

    • 对每种船类型,逐步考虑每个数量,从而保证了正确的状态转移。

    • 倒序遍历dp数组是为了避免同一个船被多次选择。

    1. 每种船的价格与载货量建立关系,形成一个二维矩阵。
    2. 对每种船类型,从1艘船到最大数量的船,逐一尝试是否加入当前组合。
    3. 更新dp数组,使得在给定预算下总载货量最大。

    2. 知识总结

    在使用豆包MarsCode AI刷题的过程中,我学到了以下几点:

    1. 动态规划(DP) :通过这道题目,我加深了对动态规划的理解,尤其是如何处理带有数量限制的背包问题。DP是解决这类问题的核心,掌握DP的状态转移和边界条件非常重要。
    2. 0/1背包与多重背包的区别:0/1背包问题中每种物品只能选择一次,而多重背包问题中可以选择多个实例,这在DP转移时要特别注意。
    3. 优化与空间复杂度:这道题目通过从后向前更新dp数组避免了多次计算相同状态,提高了算法的效率。在实际应用中,我们应当时刻考虑如何优化时间和空间复杂度。

    对于其他入门同学的建议是:在学习动态规划时,不要一开始就跳到复杂问题,先从最基础的0/1背包问题入手,理解状态转移的本质后,再挑战更复杂的问题。

    3. 学习计划

    在刷题过程中,我制定了以下学习计划:

    1. 每天刷题一定量:我每天都安排一定的时间来刷题,特别是进行深度练习,如每天做至少2道题目,从简单到中等难度,确保基础知识的巩固。
    2. 错题本:每做完一道题目,我都会将自己遇到的错误记录下来,形成错题本。然后,定期回顾这些错题,找出自己容易犯的错误,并针对性地练习相关知识点。
    3. 知识点总结:对于每个做错的题目,都会深入思考并总结经验,记下自己对知识点的理解,并思考如何在类似问题中避免犯同样的错误。
    4. 进阶学习:除了刷题外,我还结合理论学习,阅读相关书籍和文章,逐步深入到算法的各个领域,如图算法、动态规划优化等。

    4. 工具运用

    豆包MarsCode AI提供了便捷的编程题库和智能反馈系统,使我能够高效地学习和练习。然而,单纯依赖AI刷题功能是远远不够的,以下是我将AI刷题与其他学习资源结合的方式:

    1. 结合线下学习资料:在进行刷题的同时,我还会参考《算法导论》一类的书籍,深入了解算法的理论背景和推导过程,结合实际编程提高理解。
    2. 利用AI的智能反馈:每次提交代码后,AI会给出详细的分析和错误提示,这帮助我更好地理解自己在哪些细节上出现了问题,避免重复犯错。
    3. 查阅相关视频教程:对于一些特别难的题目,我会查阅网络上的视频教程,看看别人是如何思考并解决问题的。这些视频教程帮助我从不同的角度理解问题,拓宽了解题思路。
    4. 参与在线讨论与社区:利用豆包MarsCode AI的社区功能,积极参与讨论,分享自己的解题思路,也通过与他人讨论获得新的思路和技巧。

    总结

    通过在豆包MarsCode AI的刷题实践,我不仅提升了自己的编程能力,还加深了对算法和数据结构的理解。编程是一个不断学习和积累的过程,需要耐心和持续的努力。希望通过我的学习经验和心得,能够为其他正在学习编程的同学提供一些启发和帮助。