蓝桥杯之递归

1.数字三角形

题目描述

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和(路径上的每一步只可沿左斜线向下或右斜线向下走)。

输入描述

输入的第一行包含一个整数 N (1≤N≤100)N (1≤N≤100),表示三角形的行数。

下面的 NN 行给出数字三角形。数字三角形上的数都是 00 至 9999 之间的整数。

输出描述

输出一个整数,表示答案。

输入输出样例

示例

输入

复制代码
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

输出

复制代码
30

动态规划解题思路

看到"三角形最大路径和"问题,直接想到"动态规划"

动态规划的核心思想:把原问题分解为相对简单的子问题,通过求解子问题的最优解来构建原问题的最优解。

动态规划的状态转移方程:dp[i][j] = max(dp[i+1][j], dp[i+1][j+1]) + a[i][j]

利用动态规划求最大路径和的思路:从三角形的倒数第二行开始,自底向上逐层更新每个位置的最大路径和。

解题步骤模板:

复制代码
for (int i = n - 1; i > 0; i--) {
    for (int j = 1; j <= i; j++) {
        if (a[i + 1][j] >= a[i + 1][j + 1]) {
            a[i][j] += a[i + 1][j];
        } else {
            a[i][j] += a[i + 1][j + 1];
        }
    }
}
System.out.println(a[1][1]);

示例代码模板:

复制代码
import java.util.Scanner;

public class Main {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        
        // 获取行数
        int n = sc.nextInt();
        
        // 创建二维数组存储三角形
        int[][] a = new int[n + 1][n + 1];
        
        // 填充二维数组
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                a[i][j] = sc.nextInt();
            }
        }
        
        // 动态规划填充数组
        for (int i = n - 1; i > 0; i--) {
            for (int j = 1; j <= i; j++) {
                if (a[i + 1][j] >= a[i + 1][j + 1]) {
                    a[i][j] += a[i + 1][j];
                } else {
                    a[i][j] += a[i + 1][j + 1];
                }
            }
        }
        
        // 输出结果
        System.out.println(a[1][1]);
        
        sc.close();
    }
}

思维导图:

训练方法:

按照这个模板,先通过小规模示例数据测试,理解每个步骤的作用。然后尝试自己编写代码实现,确保理解每一步的逻辑。最后用大规模数据进行测试,观察性能表现,理解动态规划相比递归的优势。

2. 42点问题

题目描述

请你设计一个程序对该问题进行解答。

众所周知在扑克牌中,有一个老掉牙的游戏叫做 2424 点,选取 44 张牌进行加减乘除,看是否能得出 2424 这个答案。

现在小蓝同学发明了一个新游戏,他从扑克牌中依次抽出6张牌,注意不是一次抽出,进行计算,看是否能够组成 4242 点,满足输出 YES,反之输出 NO

最先抽出来的牌作为第一个操作数,抽出牌做第二个操作数,运算结果再当作第一个操作数,继续进行操作。

注:除不尽的情况保留整数,而且扑克牌的四张 1010 都丢了,不会出现 1010,1和A都可能出现并表示1。

请设计一个程序对该问题进行解答。

输入描述

输出仅一行包含 66 个字符。

保证字符 ∈∈ 1 2 3 4 5 6 7 8 9 J Q K A

输出描述

若给出到字符能够组成 4242 点 , 满足输出 YES,反之输出 NO

输入输出样例

示例

输入

复制代码
K A Q 6 2 3 

输出

复制代码
YES

样例说明

  • K×A=KK×A=K 即 13×1=1313×1=13
  • 13/12=113/12=1 保留整数
  • 1+6=71+6=7
  • 7∗2=147∗2=14
  • 14∗3=4214∗3=42

二维Vector逐层运算解题思路

看到"多步骤数学运算问题"或者"24点"游戏类问题,直接想到"逐层穷举所有可能"

二维Vector存储的核心思想:利用逐层运算,穷举所有可能的运算组合。

逐层运算的公式:当前层结果 = 前一层结果 ±/*// 当前数字 (注意:这里需要考虑所有运算的合法性,比如除数不能为零)

利用二维Vector逐层运算的思路:从初始值开始,逐层应用所有可能的运算,存储每一步的结果,直到达到目标层或满足某种终止条件。

解题步骤模板:

复制代码
// 定义一个二维 Vector,用于存储每一步的计算结果
Vector<Vector<Integer>> ans = new Vector<Vector<Integer>>();

// 初始化第一个元素,表示初始状态
ans.addElement(new Vector<Integer>());
ans.get(0).addElement(a[0]); // 假设 a 是一个已定义的数组,这里添加初始值

// 从第1层到第n层,逐层计算可能的运算结果
for (int i = 1; i <= n; i++) {
    // 为当前层创建一个新的 Vector
    ans.addElement(new Vector<Integer>());

    // 遍历前一层的所有元素
    for (int j = 0; j < ans.get(i - 1).size(); j++) {
        // 对当前元素进行加、减、乘、除四种运算,并将结果添加到当前层
        ans.get(i).addElement(ans.get(i - 1).get(j) + a[i]); // 加法
        ans.get(i).addElement(ans.get(i - 1).get(j) - a[i]); // 减法
        ans.get(i).addElement(ans.get(i - 1).get(j) * a[i]); // 乘法
        ans.get(i).addElement(ans.get(i - 1).get(j) / a[i]); // 除法(注意:这里没有处理除数为0的情况)
    }
}

示例代码模板:

复制代码
import java.util.Vector;

public class Main {
    public static void main(String[] args) {
        // 定义一个二维 Vector,用于存储每一步的计算结果
        Vector<Vector<Integer>> ans = new Vector<Vector<Integer>>();

        // 初始化一个数组,表示需要操作的数字
        int[] a = { 2, 3, 4, 5, 6 };

        // 初始化第一个元素,表示初始状态
        ans.addElement(new Vector<Integer>());
        ans.get(0).addElement(a[0]); // 将初始值添加到第0层

        // 从第1层到第4层,逐层计算可能的运算结果
        for (int i = 1; i <= 4; i++) {
            // 为当前层创建一个新的 Vector
            ans.addElement(new Vector<Integer>());

            // 遍历前一层的所有元素
            for (int j = 0; j < ans.get(i - 1).size(); j++) {
                // 对当前元素进行加、减、乘、除四种运算
                ans.get(i).addElement(ans.get(i - 1).get(j) + a[i]); // 加法
                ans.get(i).addElement(ans.get(i - 1).get(j) - a[i]); // 减法
                ans.get(i).addElement(ans.get(i - 1).get(j] * a[i];  // 乘法
                ans.get(i).addElement(ans.get(i - 1).get(j] / a[i]);  // 除法(注意:这里没有处理除数为0的情况)
            }
        }

        // 打印结果(这里可以选择最后一层的所有可能结果)
        System.out.println("Final results for the 5th step:");
        for (int num : ans.get(4)) {
            System.out.println(num);
        }
    }
}

思维导图:

训练方法:

  1. 先理解二维 Vector 的结构和用途,确保能够正确初始化和操作 Vector

  2. 找一个简单的例子,比如 a = {2, 3}, 手动计算可能的运算结果,然后用代码验证。

  3. 再尝试用代码实现一个复杂一点的例子,比如 a = {2, 3, 4}, 观察输出结果是否符合预期。

  4. 考虑特殊情况,如除数为零的情况,添加相应的错误处理代码。

  5. 优化代码,避免重复计算,提高效率。

自学蓝桥杯笔记,希望我们可以一起学习!

相关推荐
CHQIUU4 分钟前
Java 设计模式心法之第4篇 - 单例 (Singleton) 的正确打开方式与避坑指南
java·单例模式·设计模式
碎梦归途7 分钟前
23种设计模式-结构型模式之享元模式(Java版本)
java·开发语言·jvm·设计模式·享元模式
明月看潮生9 分钟前
青少年编程与数学 02-018 C++数据结构与算法 06课题、树
数据结构·c++·算法·青少年编程·编程与数学
宇柔11 分钟前
JavaEE学习笔记(第二课)
笔记·学习·java-ee
小指纹11 分钟前
动态规划(一)【背包】
c++·算法·动态规划
_安晓19 分钟前
数据结构 -- 图的应用(一)
数据结构·算法·图论
lozhyf27 分钟前
Eureka搭建
java·spring cloud
阳洞洞30 分钟前
leetcode 二分查找应用
算法·leetcode·二分查找
猎猎长风31 分钟前
【数据结构和算法】1. 数据结构和算法简介、二分搜索
数据结构·算法
Pasregret34 分钟前
模板方法模式:定义算法骨架的设计模式
算法·设计模式·模板方法模式