大一学生分享蓝桥杯比赛经典例题42点问题-枚举算法

砥砺前行,智慧点亮未来。

                                        ---同行者联盟

枚举法

图片

枚举算法的思想:

枚举算法的核心思想是将问题的所有可能成为答案的解一一列举,然后根据问题给定的条件判断这些解是否合适。对于符合条件的解,保留;反之则舍弃。

枚举算法解题的基本思路:

  1. 确定枚举解的范围和判断条件: 在开始解题之前,需要明确枚举的解范围,并定义问题的判断条件。

  2. 选取合适的枚举方法: 选择适当的枚举方式进行逐一枚举,确保覆盖所有可能的解。避免遗漏任何真正的解,同时注意防止重复。

  3. 使用判断条件检验解: 在枚举过程中,应用事先确定的判断条件验证每个解的合法性,保留符合要求的解。

枚举算法的一般步骤:

  1. 确定范围和枚举方式: 根据题目确定枚举的范围,并选择合适的枚举方式。确保不遗漏任何真正的解,同时避免重复。

  2. 优化解空间: 查看是否存在优化的可能性,以缩小可能成为解的答案范围,提高解决问题的效率。

  3. 定义准确验证条件: 根据问题找到准确、易编码的验证条件,用于检验每个可能的解。

  4. 枚举和判断: 逐一枚举解并验证是否符合事先确定的条件,保留符合条件的解。

  5. 输出结果: 按照要求输出枚举过程中留下的符合条件的解。

简单型枚举

简单型枚举是通过简单的 for 循环嵌套解决的问题类型。

这种枚举方式没有特定的固定枚举模式,而且相对简单。只需按照题目的要求设计代码即可完成解题。

让我们通过一个示例题目来复习一下。

42 点问题

题目描述:

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

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

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

除不尽的情况保留整数。

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

样例

输入 :K A Q 6 2 3

输出:YES

对于上面的样例我们进行了如下计算;

K*A=K 即 13*1=13

13/12=1 保留整数

1+6=7

7*2=14

14*3=42

题目解析:

这个题目我们可以依次枚举数字,然后在枚举数字间的符号即可。由于到结果之间进行了三步计算,所以我们这里需要进行一个递归操作,利用了上节课讲解的知识。

两重循环即可解决问题,伪代码如下:

op1 赋值为 第一个数

op(op[1] op[2])
{

    for op in [+ - * /]
       ans = 第一个操作数op1 操作 第二个操作数op2

        如果是第六个操作数,就检验是否符合要要求 ==42?如果是就返回True

        如果op(ans , op[3]) 返回 True,就返回True 因为找到了答案,否则就继续进行

    没有找到答案返回False
}

但是思路很清晰,写起来却非常的复杂,我们使用我们讲过的 List 来优化这个枚举方式。

代码(Java语言):​​​​​​​

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {

    // 存放我们获取的六张牌数值
    static int[] a = new int[6];

    static List<List<Integer>> ans = new ArrayList<>();

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        // 选了六张牌
        for (int i = 0; i < 6; i++) {
            // 初始化ans
            ans.add(new ArrayList<>());

            char c = in.next().charAt(0);
            // 将字符设置为对应的数字
            if (c == 'A') {
                a[i] = 1;
            } else if (c == 'J') {
                a[i] = 11;
            } else if (c == 'Q') {
                a[i] = 12;
            } else if (c == 'K') {
                a[i] = 13;
            } else {
                a[i] = (c - '0');
            }
        }

        // 先选中第一张牌,此时不进行任何处理
        ans.get(0).add(a[0]);
        // 接下来的每张牌中,和现有结果可以做+-*/运算
        for (int i = 1; i <= 5; i++) {
            for (int j = 0; j < ans.get(i - 1).size(); j++) {
                // 基于上一轮的结果(存了+-*/的结果) 与当前抽到的牌做加法运算
                ans.get(i).add(ans.get(i - 1).get(j) + a[i]);
                // 基于上一轮的结果(存了+-*/的结果) 与当前抽到的牌做-运算
                ans.get(i).add(ans.get(i - 1).get(j) - a[i]);
                // 基于上一轮的结果(存了+-*/的结果) 与当前抽到的牌做*运算
                ans.get(i).add(ans.get(i - 1).get(j) * a[i]);
                // 基于上一轮的结果(存了+-*/的结果) 与当前抽到的牌做/运算
                ans.get(i).add(ans.get(i - 1).get(j) / a[i]);
            }
        }
        int flag = 0;
        for (int i = 0; i < ans.get(5).size(); i++) {
            //检查最后一次牌后的结果,如果有为42的,flag设置为1,代表符合42点要求
            if (ans.get(5).get(i) == 42) {
                flag = 1;
                break;
            }
        }
        if (flag == 1) {
            System.out.println("YES");
        }else {
            System.out.println("NO");
        }
    }
}

学生分享视频

简单型枚举

招生:

现特邀P8大佬,哈工程研究生毕业者授数据结构与算法,带领大家学习300道经典算法题,有意向的可以沟通+V 17865578823

  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值