实践记录及工具使用 | 豆包MarsCode AI 刷题

122 阅读10分钟

一、实践背景

在编程学习过程中,遇到难题时往往需要寻求帮助。传统的求助方式可能包括向老师、同学请教,或者查阅相关资料。然而,这些方式有时可能不够及时。AI代码陪练则没有以上苦恼,为编程学习者提供了一个全新而便捷的学习辅助工具。

二、AI代码陪练功能介绍

AI代码陪练是一种基于人工智能技术的学习辅助工具,它可以根据学习者的需求和水平,提供个性化的编程学习支持。以下是对AI代码陪练主要功能的介绍:

解题思路:当学习者对题目有疑问或不解时,陪练会提供清晰的解题思路,帮助学习者理解如何解决问题。

代码修改建议:在编写代码的过程中,学习者可能会遇到各种问题或错误。陪练会根据学习者的当前代码,提供针对性的修改建议,帮助学习者完善和优化代码。

伪代码或代码框架:为了降低编程的难度,陪练可以为学习者提供伪代码或代码框架,作为编程的起点,帮助学习者更快地进入编程状态。

错误排查:当学习者运行代码时遇到错误,陪练会根据命令行输出等信息,帮助学习者定位问题所在,并提供解决方案。

最终答案:如果学习者在多次尝试后仍然无法解决问题,陪练可以提供最终答案。但建议学习者在查看答案之前,先尝试自己解决问题,以培养独立思考和解决问题的能力。

三、实践过程与体验

为了深入了解AI代码陪练的功能和效果,我进行了一系列的实践探索。下面我将以No.83题“小S的货船租赁冒险”为例,解释代码陪练能帮我什么。

问题描述

小S在码头租用货船,有 Q 种不同类型的货船可供选择。每种货船有固定的数量 m[i]、租赁成本 v[i] 和最大载货量 w[i]。小S希望在预算 V 元内,租用能够承载最大总货物的货船组合。每种货船的具体信息包括数量、租赁价格和载货量。小S需要你帮忙计算在给定预算下,她能租用的货船的最大总载货量是多少。

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

测试样例

样例1:

输入:Q = 2,V = 10,ships = [[2, 3, 2], [3, 2, 10]]
输出:32

样例2:

输入:Q = 3,V = 50,ships = [[5, 10, 20], [2, 20, 30], [3, 15, 25]]
输出:100

样例3:

输入:Q = 1,V = 100,ships = [[10, 5, 50]]
输出:500

样例4:

输入:Q = 4,V = 100,ships = [[1, 100, 200], [2, 50, 100], [3, 33, 66], [4, 25, 50]]
输出:200

样例5:

输入:Q = 2,V = 300,ships = [[100, 1, 1], [50, 5, 10]]
输出:550

代码陪练在解决编程问题时可以提供以下帮助:

  1. 理解题目要求

    • 帮助我明确题目中的关键点,如预算限制、货船的种类和数量、租赁成本和载货量等。
  2. 数据结构和算法选择

    • 指导我选择合适的数据结构和算法来解决问题。例如,本题中使用动态规划(Dynamic Programming)来解决背包问题。
  3. 代码框架搭建

    • 提供代码的基本框架,帮助我快速开始编写代码。例如,初始化动态规划数组、遍历货船种类和预算等。
  4. 代码实现细节

    • 在编写代码时,提供具体的实现细节,如如何更新动态规划数组、如何处理不同数量的货船等。
  5. 错误排查和优化

    • 当我遇到错误或性能问题时,帮助我分析代码中的问题,并提供优化建议。例如,检查循环边界、数组越界等问题。
  6. 测试和验证

    • 提供测试用例,帮助我验证代码的正确性。例如,使用题目中给出的测试样例来检查代码输出是否符合预期。
  7. 学习资源和参考

    • 提供相关的学习资源和参考资料,帮助我深入理解相关概念和算法。

以下是对代码陪练部分功能的测试:

1.

Q: 给我一些思路和代码提示。

A:

问题理解

首先,我们需要理解问题的核心:在给定的预算 V 元内,选择不同类型的货船,使得总载货量最大化。每种货船有固定的数量、租赁成本和载货量。

数据结构选择

我们选择使用动态规划(DP)来解决这个问题。动态规划是一种通过将问题分解为子问题并存储子问题的解来解决复杂问题的方法。

算法步骤

  1. 初始化DP数组:我们使用一个一维数组 dp,其中 dp[j] 表示使用不超过 j 元的预算所能获得的最大载货量。
  2. 遍历每种货船:我们遍历每种货船,获取其数量、租赁成本和载货量。
  3. 逆序遍历预算:通过逆序遍历预算,我们可以避免在更新 dp 数组时覆盖之前的值,从而避免重复计算。
  4. 更新DP数组:对于每种货船,我们考虑选择不同数量的该种货船,并更新 dp 数组。
  5. 返回结果:最终返回 dp[V],即在预算 V 元内所能获得的最大载货量。

代码实现

以下是详细的代码实现:

import java.util.List;

public class Main {
    public static int solution(int Q, int V, List<List<Integer>> ships) {
        // 初始化 dp 数组,dp[j] 表示使用不超过 j 元的预算所能获得的最大载货量
        int[] dp = new int[V + 1];

        // 遍历每种货船
        for (int i = 0; i < Q; i++) {
            int m = ships.get(i).get(0); // 该种货船的数量
            int v = ships.get(i).get(1); // 该种货船的租赁成本
            int w = ships.get(i).get(2); // 该种货船的载货量

            // 逆序遍历预算,避免重复计算
            for (int j = V; j >= v; j--) {
                // 考虑选择不同数量的该种货船
                for (int k = 1; k <= m && k * v <= j; k++) {
                    // 更新 dp 数组
                    dp[j] = Math.max(dp[j], dp[j - k * v] + k * w);
                }
            }
        }

        // 返回最大载货量
        return dp[V];
    }

    public static void main(String[] args) {
        // 测试用例
        List<List<Integer>> ships = List.of(List.of(2, 3, 2), List.of(3, 2, 10));
        System.out.println(solution(2, 10, ships) == 32);
    }
}

关键步骤解释

  1. 初始化DP数组:我们使用一个一维数组 dp 来存储每个预算下的最大载货量。
  2. 遍历每种货船:我们遍历每种货船,获取其数量、租赁成本和载货量。
  3. 逆序遍历预算:通过逆序遍历预算,我们可以避免在更新 dp 数组时覆盖之前的值,从而避免重复计算。
  4. 更新DP数组:对于每种货船,我们考虑选择不同数量的该种货船,并更新 dp 数组。
  5. 返回结果:最终返回 dp[V],即在预算 V 元内所能获得的最大载货量。

总结

通过使用动态规划和一维DP数组,我们能够有效地解决这个问题,并且在遍历预算时使用逆序遍历来避免重复计算,从而提高代码的性能。

如果你有任何问题或需要进一步的帮助,请告诉我!

2.

对于错误代码:


public class Main {
    public static int solution(int Q, int V, List<List<Integer>> ships) {
        // 初始化 dp 数组,dp[i][j] 表示在前 i 种货船中,使用不超过 j 元的预算所能获得的最大载货量
        int[][] dp = new int[Q + 1][V + 1];

        // 遍历每种货船
        for (int i = 1; i <= Q; i++) {
            int m = ships.get(i - 1).get(0); // 该种货船的数量
            int v = ships.get(i - 1).get(1); // 该种货船的租赁成本
            int w = ships.get(i - 1).get(2); // 该种货船的载货量

            // 遍历预算
            for (int j = 0; j <= V; j++) {
                // 考虑选择不同数量的该种货船
                for (int k = 0; k <= m; k++) {
                    // 错误:这里没有检查预算是否足够
                    dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v] + k * w);
                }
            }
        }

        // 返回最大载货量
        return dp[Q][V];
    }

    public static void main(String[] args) {
        // 测试用例
        List<List<Integer>> ships = List.of(List.of(2, 3, 2), List.of(3, 2, 10));
        System.out.println(solution(2, 10, ships) == 32);
    }
}

Q:帮我检查一下代码。

A: 你的代码总体思路是正确的,使用动态规划来解决这个问题。但是,你在代码中有一个关键的错误,即在更新 dp[i][j] 时没有检查当前预算 j 是否足够支付 k 艘货船的租赁成本。

错误点

在你的代码中,这一行:

dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v] + k * w);

没有检查 j - k * v 是否小于 0。如果 j - k * v 小于 0,那么 dp[i - 1][j - k * v] 是无效的,因为预算不能为负数。

修改建议

你需要在更新 dp[i][j] 之前,检查 j - k * v 是否大于等于 0。如果小于 0,则跳过这个更新。

修改后的代码

import java.util.List;

public class Main {
    public static int solution(int Q, int V, List<List<Integer>> ships) {
        // 初始化 dp 数组,dp[i][j] 表示在前 i 种货船中,使用不超过 j 元的预算所能获得的最大载货量
        int[][] dp = new int[Q + 1][V + 1];

        // 遍历每种货船
        for (int i = 1; i <= Q; i++) {
            int m = ships.get(i - 1).get(0); // 该种货船的数量
            int v = ships.get(i - 1).get(1); // 该种货船的租赁成本
            int w = ships.get(i - 1).get(2); // 该种货船的载货量

            // 遍历预算
            for (int j = 0; j <= V; j++) {
                // 考虑选择不同数量的该种货船
                for (int k = 0; k <= m; k++) {
                    // 检查预算是否足够
                    if (j >= k * v) {
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * v] + k * w);
                    }
                }
            }
        }

        // 返回最大载货量
        return dp[Q][V];
    }

    public static void main(String[] args) {
        // 测试用例
        List<List<Integer>> ships = List.of(List.of(2, 3, 2), List.of(3, 2, 10));
        System.out.println(solution(2, 10, ships) == 32);
    }
}

解释

  • 检查预算是否足够:在更新 dp[i][j] 之前,检查 j >= k * v,确保当前预算 j 足够支付 k 艘货船的租赁成本。
  • 动态规划更新:只有在预算足够的情况下,才更新 dp[i][j]

这样修改后,你的代码应该能够正确计算在给定预算下,能够租用的货船的最大总载货量。

AI代码陪练功能可以辅助我们进行代码编写、调试和优化,使我们高效地解决遇到的问题,更好地完成任务。

四、总结

AI代码陪练是编程学习领域的一项创新工具,它基于人工智能技术,为学习者提供个性化的学习支持。通过提供清晰的解题思路、针对性的代码修改建议、伪代码或代码框架、错误排查以及最终答案等功能,AI代码陪练有效地解决了传统求助方式时效性不足的问题。它不仅能够帮助学习者快速理解并解决编程难题,还能够培养学习者的独立思考和解决问题的能力。因此,AI代码陪练成为了编程学习者不可或缺的学习辅助工具。