华为OD机试 - 24点游戏算法(Python/JS/C/C++ 牛客练习题)

在这里插入图片描述

2025华为OD机试题库(按算法分类):2025华为OD统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

一、题目描述

给出4个1-10的数字,通过加减乘除运算,得到数字为24就算胜利,除法指实数除法运算,运算符仅允许出现在两个数字之间,本题对数字选取顺序无要求,但每个数字仅允许使用一次,且需考虑括号运算
此题允许数字重复,如3 3 4 4为合法输入,此输入一共有两个3,但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。

二、输入描述

读入4个[1,10]的整数,数字允许重复,测试用例保证无异常数字。

三、输出描述

对于每组案例,输出一行表示能否得到24点,能输出true,不能输出false。

四、测试用例

1、输入

7 2 1 10

2、输出

true

五、解题思路

  1. 首先读取输入的四个整数;
  2. 使用深度优先搜索(DFS)算法尝试所有可能的运算组合;
  3. 定义一个全局变量 flag,用于表示是否能得到结果为24的运算;
  4. 定义一个数组 nums 存储四个输入的整数;
  5. 定义一个布尔数组 visit,用于标记数字是否已经被使用过;
  6. 实现递归函数 dfs,函数参数为当前已经使用的数字个数 u 和运算的中间结果 tmp;
  7. 递归终止条件为已经使用了四个数字且结果为24,设置 flag 为1,表示能得到结果为24,返回 true;
  8. 遍历四个数字,如果数字没有被使用过,则将其标记为已使用,并尝试加减乘除四种运算;
  9. 如果通过递归调用可以得到结果为24,返回 true;
  10. 如果无法得到结果为24,则将当前数字标记为未使用,相当于回溯操作;
  11. 如果所有数字都尝试完毕后仍无法得到结果为24,返回 false;
  12. 在主函数中调用 dfs 函数,并输出 flag 的值;

六、Python算法源码

# 定义求解24点问题的递归函数,参数为数字列表
def solve(nums):
    # 如果列表中只有一个数字,则判断其是否等于24(允许1e-6的浮点误差)
    if len(nums) == 1:
        return abs(nums[0] - 24) < 1e-6
    # 遍历列表中所有两两组合
    for i in range(len(nums)):
        for j in range(len(nums)):
            if i == j:
                continue  # 跳过相同下标
            # 构造新的数字列表,将未选中的数字加入
            next_nums = [nums[k] for k in range(len(nums)) if k != i and k != j]
            a = nums[i]
            b = nums[j]
            # 计算可能的运算结果,包括加、减、反向减、乘、除(注意判断除数不为0)
            candidates = [a + b, a - b, b - a, a * b]
            if abs(b) > 1e-6:
                candidates.append(a / b)
            if abs(a) > 1e-6:
                candidates.append(b / a)
            # 对每个候选结果递归求解
            for candidate in candidates:
                next_nums.append(candidate)
                if solve(next_nums):
                    return True
                next_nums.pop()  # 回溯,移除最后添加的候选结果
    return False

# 主函数:读取输入,测试求解结果
if __name__ == '__main__':
    # 输入示例:输入"7 2 1 10"(数字间以空格分隔)
    inp = input().strip().split()
    nums = list(map(float, inp))
    # 输出结果转换为小写的字符串 "true" 或 "false"
    print(str(solve(nums)).lower())

七、JavaScript算法源码

// 定义求解24点问题的递归函数,参数为数字数组
function solve(nums) {
    // 如果数组中只剩下一个数字,则判断其是否接近24(允许浮点误差1e-6)
    if (nums.length === 1) {
        return Math.abs(nums[0] - 24) < 1e-6;
    }
    // 遍历数组中所有两两组合
    for (let i = 0; i < nums.length; i++) {
        for (let j = 0; j < nums.length; j++) {
            if (i === j) continue; // 跳过同一位置
            // 构造新数组,将未使用的数字加入
            let nextNums = [];
            for (let k = 0; k < nums.length; k++) {
                if (k !== i && k !== j) {
                    nextNums.push(nums[k]);
                }
            }
            let a = nums[i], b = nums[j];
            // 计算所有可能的运算结果
            let candidates = [a + b, a - b, b - a, a * b];
            if (Math.abs(b) > 1e-6) candidates.push(a / b);
            if (Math.abs(a) > 1e-6) candidates.push(b / a);
            // 对每个候选结果递归求解
            for (let candidate of candidates) {
                nextNums.push(candidate);
                if (solve(nextNums)) return true;
                nextNums.pop(); // 回溯,移除最后添加的候选结果
            }
        }
    }
    return false;
}

// 主函数:接收输入字符串并输出结果
// 这里假设输入为类似 "7 2 1 10" 的字符串
function main(input) {
    // 按空格拆分输入字符串得到各个数字
    let parts = input.trim().split(/\s+/);
    // 将每个数字字符串转换为浮点数
    let nums = parts.map(x => parseFloat(x));
    // 输出求解结果
    console.log(solve(nums));
}

// 调用主函数进行测试
main("7 2 1 10");

八、C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>

// 定义浮点数误差范围
#define EPS 1e-6

// 递归函数:nums数组中有n个数字,判断是否能运算得到24
bool solve(double nums[], int n) {
    // 如果只剩下一个数字,则判断其是否接近24
    if (n == 1) {
        return fabs(nums[0] - 24) < EPS;
    }
    // 遍历所有两两组合
    for (int i = 0; i < n; i++) {
        for (int j = i+1; j < n; j++) {
            double a = nums[i], b = nums[j];
            // 枚举可能的运算结果,最多6种
            double candidates[6];
            int count = 0;
            candidates[count++] = a + b;
            candidates[count++] = a - b;
            candidates[count++] = b - a;
            candidates[count++] = a * b;
            if (fabs(b) > EPS)
                candidates[count++] = a / b;
            if (fabs(a) > EPS)
                candidates[count++] = b / a;
            
            // 为下一个递归层次构造新数组 newNums,大小为 n-1
            double newNums[4];
            // 将未使用的数字放入 newNums
            for (int k = 0, idx = 0; k < n; k++) {
                if (k != i && k != j) {
                    newNums[idx++] = nums[k];
                }
            }
            // 对每个候选运算结果,加入 newNums 后递归判断
            for (int c = 0; c < count; c++) {
                newNums[n - 1] = candidates[c];  // 将候选结果放入末尾
                if (solve(newNums, n - 1))
                    return true;
            }
        }
    }
    return false;
}

int main() {
    // 读取输入,假设输入为一行4个数字,以空格分隔
    double nums[4];
    while (scanf("%lf %lf %lf %lf", &nums[0], &nums[1], &nums[2], &nums[3]) == 4) {
        // 判断是否能得到24,输出 true 或 false
        if (solve(nums, 4))
            printf("true\n");
        else
            printf("false\n");
    }
    return 0;
}

九、C++算法源码

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

// 定义浮点误差范围
const double EPS = 1e-6;

// 递归函数:参数nums为当前剩余数字的vector,判断能否运算得到24
bool solve(vector<double>& nums) {
    // 当只有一个数字时,判断其是否接近24
    if (nums.size() == 1)
        return fabs(nums[0] - 24) < EPS;
    // 遍历所有两两组合
    for (int i = 0; i < nums.size(); i++) {
        for (int j = i + 1; j < nums.size(); j++) {
            double a = nums[i], b = nums[j];
            // 构造一个新vector,存放未使用的数字
            vector<double> nextNums;
            for (int k = 0; k < nums.size(); k++) {
                if (k != i && k != j)
                    nextNums.push_back(nums[k]);
            }
            // 计算所有可能的运算结果
            vector<double> candidates = {a + b, a - b, b - a, a * b};
            if (fabs(b) > EPS)
                candidates.push_back(a / b);
            if (fabs(a) > EPS)
                candidates.push_back(b / a);
            // 对每个候选结果递归求解
            for (double candidate : candidates) {
                nextNums.push_back(candidate);
                if (solve(nextNums))
                    return true;
                nextNums.pop_back();  // 回溯,移除最后添加的候选结果
            }
        }
    }
    return false;
}

int main() {
    // 读取一行4个数字,以空格分隔
    double a, b, c, d;
    while (cin >> a >> b >> c >> d) {
        vector<double> nums = {a, b, c, d};
        cout << (solve(nums) ? "true" : "false") << endl;
    }
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2025 A卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值