困难题:魔法甜点之和:小包的新挑战| 豆包MarsCode AI刷题

200 阅读5分钟

解题思路与代码结构分析

题目解析

题目描述了小R想通过选择若干个甜点,使得它们的喜爱值之和满意他的预期值 S。同时,小R可以使用魔法棒将某些甜点的喜爱值修改为其阶乘。通过选择甜点和使用魔法棒的组合,小R要实现总和恰好为 S 的目标。

要解决这个问题,可以使用动态规划(Dynamic Programming)的思想,因为这个问题涉及到组合选择,且需要计算满足条件的不同方案的数量。

解题思路

  1. 动态规划状态定义:

    • 使用三维数组 dp[n + 2][s + 1][m + 1],其中:

      • n 表示在考虑到第 n 个甜点。
      • s 表示当前的喜爱值和。
      • m 表示当前已使用的魔法棒的数量。
    • dp[i][k][j] 表示在考虑前 i 个甜点中,恰好用 j 个魔法棒售得最喜爱的价值为 k 的方案数。

  2. 状态转移:

    • 不选择当前甜点:  dp[i][k][j] = dp[i - 1][k][j]

    • 选择当前甜点:

      • 如果直接选择该甜点,增加其喜爱值:if (k >= likes[i]) dp[i][k][j] += dp[i - 1][k - likes[i]][j]
      • 如果使用魔法棒变更该甜点的喜爱值为其阶乘,且该甜点的原值在允许的范围内(如 <= 7):if (j >= 1 && likes[i] <= 7 && k >= jiecheng(likes[i])) { dp[i][k][j] += dp[i - 1][k - jiecheng(likes[i])][j - 1]; }
  3. 边界情况与初始化:

    • 当没有任何甜点时且目标值为 0,只有一种方案(不选择任何甜点),因此 dp[j][0][i] = 1

题目解题代码

public class Main {
    public static int solution(int n, int m, int s, int[] like) {
        int dp[][][] = new int[n + 2][s + 1][m + 1];
        // dp[n][s][m] 在0-n个物品中,有m次魔法机会,获得美味值为s的方案数目
        for (int i = 0; i <= m; i++)
            for (int j = 0; j <= n; j++)
                dp[j][0][i] = 1;
        int likes[] = new int[like.length + 1];
        for (int i = 0; i < like.length; i++)
            likes[i + 1] = like[i];// 平移

        for (int i = 1; i <= n; i++) {
            for (int k = 0; k <= s; k++) {
                for (int j = 0; j <= m; j++) {

                    dp[i][k][j] = dp[i - 1][k][j];
                    if (k >= likes[i])
                        dp[i][k][j] += dp[i - 1][k - likes[i]][j];
                    // 限制 7之后的阶乘不需要计算
                    if (j >= 1 && likes[i] <= 7 && k >= jiecheng(likes[i])) {
                        dp[i][k][j] += dp[i - 1][k - jiecheng(likes[i])][j - 1];
                    }
                }
            }
        }
        // System.out.println( dp[n][s][m]);
        return dp[n][s][m];
    }
    public static int jiecheng(int x) {
        int t = 1;
        for (int i = 1; i <= x; i++) {
            t *= i;
        }
        return t;
    }
    public static void main(String[] args) {
        // You can add more test cases here
        int[] like1 = { 1, 2, 3 };
        int[] like2 = { 1, 1, 1 };
        System.out.println(solution(3, 2, 6, like1) == 5);
        System.out.println(solution(3, 1, 1, like2) == 6);
    }
}

代码结构分析

代码的主体结构如下:

  1. 函数 solution

    • 接收输入参数(甜点数量、魔法棒数量、目标值和喜爱值数组),并初始化 DP 表。
    • 通过三重循环,更新 dp 表的状态。
    • 返回满足条件的方案数。
  2. 函数 jiecheng

    • 计算给定数字的阶乘,仅在处理喜爱值不大于 7 的情况下使用,因为超过 7 的阶乘会导致数字过大。
  3. 主函数 main

    • 测试 solution 方法,输出不同情况的结果,可以扩展更多测试用例以验证功能的正确性。

AI 辅助刷题的好处

  1. 快速获取思路与解决方案:

    • AI 可以在短时间内给出问题的整体解析与解决方案,使得学习者可以快速了解问题背后的逻辑。但是千万别借此养成了不动脑的习惯。先思考一下大体的思路,写出来大体框架的代码,看看能不能完成样例,对于针对性和繁琐的细节修改可以交给AI来帮忙完成。
  2. 针对性学习:

    • 在 AI 的辅助下,学习者可以根据做错的题目获得针对性的学习建议,帮助他们强化薄弱环节,提升学习效率。
  3. 高效资源利用:

    • AI 能够整合各类学习资源,包括书籍、在线资料和代码示例,提供个性化的学习路径。
  4. 实践与反馈:

    • AI 可以根据学习者的进度提供实时反馈,引导学习者调整学习策略,激发主动学习的动力。
  5. 增强信心:

    • 通过 AI 模拟考试或练习,学习者获得及时反馈,有助于增强信心,从而更有效地准备正式机测的考试或面试。
  6. 降低学习门槛:

    • AI 技术能够将复杂的学习材料转化为易于理解、可视化的内容,使得知识的获取变得更加直观和轻松。这对于初学者特别重要,因为他们往往在学习过程中面临知识的“死角”。

总结

通过这道题目的练习,我们不仅学会了如何利用动态规划解决组合问题,还深刻理解了 AI 在学习过程中所带来的便利和效率提升。在未来学习的道路上,我们可以结合 AI 辅助刷题功能与其他学习方法,共同助力我们的学习成效。

AI 辅助学习不仅提升了教育的质量和效率,也在不断改变学习者的学习体验和习惯。通过个性化的学习方式、实时反馈和丰富的资源,AI 正在引领教育的未来,使每个学习者都能在更高效的环境中成长。无论是初学者还是专业人士,善用 AI 学习工具都能为我们带来意想不到的学习效果。希望每位学习者都能在 AI 的助力下,走得更远,学得更好。

我是北恒吖,一名普通大二学生,志愿于冲刺大厂,与君同勉,脚踏实地,仰望星空,明天再见。