C++ 实现计算24点

article/2025/10/24 6:42:55

原理

暴力枚举所有的情况,运算符号4个,加减乘除 + - * / ,整数数字4个(易扩展为5个数或者更多)。所需要枚举的次数:

  1. 数字顺序:4个数的全排列,4! = 24
  2. 运算符号:4个数需要3个符号,每个可选4种,43 = 64
  3. 加括号方式:((AB)C)D(A(BC))D(AB)(CD)A((BC)D)A(B(CD)),共5种。
  4. 枚举次数 24*64*5

实现细节

  • 全排列枚举由库函数 next_permutation来完成枚举
  • 64种运算符号搭配由一个整数状压(0—63)来完成枚举
  • 加括号方式由后缀表达式来完成,运算对象用0表示,运算符用1表示,由右向左开始,以(A-(B+C))*D为例,转成后缀表达式为ABC+-D*,改成由右向左阅读的顺序,*D-+CBA,再转成用01标记的二进制数1011000,为了在代码中便于对运算符和运算对象同时操作,去掉最后一个0,变为101100,去掉的那个在初始时提前压栈,这样就正好3个0、3个1了,同理,((AB)C)D->101010(AB)(CD)->110010A((BC)D)->110100A(B(CD))->111000
  • 由于运算过程中含有除法,用double又不是我风格,所以写个小结构体表示有理数。包含分子和分母。
  • 验证是否有解和打印解分开,更灵活。

代码

运算过程和模拟计算后缀表达式差不多,一个原理。

#include <bits/stdc++.h>
#define top_and_pop(stack, var) var=stack.top();stack.pop()
using namespace std;
//运算 + - * / , 数量 num_n = 4
const int num_n = 4, max_oper = 1 << (2*num_n - 2);
struct Num {int a, b;Num(int ta = 0, int tb = 1) : a(ta), b(tb) {if(b < 0)a = -a, b = -b;int g = __gcd(abs(a), b);a /= g, b /= g;}
};
// 候选的后缀表达式所代表的整数值
int methods[5] = {0b101010, 0b101100, 0b110010, 0b110100, 0b111000};
bool hasAnswer(int* arr, int oper_code, int method) {stack<int> ops;stack<Num> nums;int arr_pos = 0;nums.push(Num(arr[arr_pos++]));while(method) {if(method & 1) {Num x,y;top_and_pop(nums, y);top_and_pop(nums, x);switch(ops.top()) {case 0: // +nums.push({x.a * y.b + x.b * y.a, x.b * y.b});break;case 1: // -nums.push({x.a * y.b - x.b * y.a, x.b * y.b});break;case 2: // *nums.push({x.a * y.a, x.b * y.b});break;case 3: // /if(y.a == 0)return false;nums.push({x.a * y.b, x.b * y.a});break;}ops.pop();} else {nums.push(Num(arr[arr_pos++]));ops.push(oper_code & 3);oper_code >>= 2;}method >>= 1;}return nums.top().a == 24 && nums.top().b == 1;
}
void printAnswer(int* arr, int oper_code, int method) {const char* operstr = "+-*/";string zuo = "(", you = ")", s1, s2;stack<char> ops;stack<string> str;int arr_pos = 0;str.push(to_string(arr[arr_pos++]));while(method) {if(method & 1) {top_and_pop(str, s2);top_and_pop(str, s1);str.push(zuo + s1 + ops.top() + s2 + you);ops.pop();} else {str.push(to_string(arr[arr_pos++]));ops.push(operstr[oper_code & 3]);oper_code >>= 2;}method >>= 1;}string res = str.top();cout << res.substr(1, res.length() - 2) << endl;
}
int arr[num_n]; // 4 个数字
int main() {int t;cin >> t;
outer_loop:while(t--) {for(int i = 0; i < num_n; i++) {cin >> arr[i];}sort(arr, arr + num_n);do {for(int meth : methods) {for(int oper = 0; oper < max_oper; oper++) {if(hasAnswer(arr, oper, meth)) {printAnswer(arr, oper, meth);goto outer_loop; // break multiloop}}}} while(next_permutation(arr, arr + num_n));cout << "No solution" << endl;}
}

测试

注: 第一个数是测试组数
在这里插入图片描述

扩展

上述代码可以很容易的扩展成多个数字,比如对5个数字进行24点计算。把 num_n 改为5,然后再修改一下 methods 数组为

int methods[14] = {0b10101010,0b10101100,0b10110010,0b10110100,0b10111000,0b11001010,0b11001100,0b11010010,0b11010100,0b11011000,0b11100010,0b11100100,0b11101000,0b11110000};

其中14就是5个数字加括号一共的种类数,他是卡特兰数。其实上面那一串二进制数是有规律的,所以可以写代码来生成,而不需要手算。
其实,也可以写成递归版的,就不需要算这些后缀表达式了。改天写一写。

5个数24点测试

在这里插入图片描述


http://chatgpt.dhexx.cn/article/BQrOXXmV.shtml

相关文章

计算机上的24点游戏怎么玩,趣味算数二十四点游戏规则怎么玩技巧

概述&#xff1a;这是一个算数游戏&#xff0c;用四张牌计算得出24。 时间&#xff1a;20分钟 人数&#xff1a;集体参与 目的&#xff1a;锻炼学员的快速计算能力。 道具&#xff1a;扑克牌 步骤&#xff1a; 1.去点大小王&#xff0c;“K”计13点&#xff0c;“Q”计12点&…

【编程|二十四点】关于编程解决二十四点的两种思路

【编程心得系列*24点】 写在前面&#xff1a;编程心得系列不谈具体问题的代码&#xff0c;只谈解决思路。 这是一个关于二十四点的软件。属于典型的先有目的再有初衷的软件。 在此之前我倒是写过一个解数独的软件。但那个的核心代码部分毕竟是抄袭的。这次是觉得对自己更有信…

计算机二十四点游戏怎么玩,扑克牌二十四点怎么玩?扑克牌二十四点游戏规则介绍...

扑克牌二十四点是在国际上很流行的一种扑克游戏玩法&#xff0c;因为游戏计算性较强&#xff0c;较为考验的玩家的心算能力&#xff0c;所以很受扑克玩家的喜爱&#xff0c;那么扑克牌二十四点到底是怎么玩的呢&#xff1f;扑克牌二十四点的游戏规则又是什么呢&#xff1f;下面…

CCF计算机软件能力认证试题练习:201903-2 二十四点

二十四点 来源&#xff1a;CCF 标签&#xff1a; 参考资料&#xff1a; 相似题目&#xff1a; 背景 二十四点是一款著名的纸牌游戏&#xff0c;其游戏的目标是使用 3 个加减乘除运算使得 4张纸牌上数字的运算结果为 24。 题目 定义每一个游戏由 4 个从 1-9 的数字和 3 个四则运…

asdasdas

asdasdasdsadassad 阅读全文: http://gitbook.cn/gitchat/activity/5d634f8c5cbc425420e0e72f 您还可以下载 CSDN 旗下精品原创内容社区 GitChat App &#xff0c;阅读更多 GitChat 专享技术内容哦。

dsada

图2.2 www.sina.com网站系统采用的基本上就是图2.2所示的架构&#xff0c;不同地区的人们在访问www.sina.com站点时&#xff0c;浏览器实际上所访问的服务器是不一样的&#xff0c;例如&#xff0c;吉林省的用户访问的服务器实际是sina放在吉林地区的代理服务器&#xff0c;湖北…

Asdasd

这里写阿阿萨德斯达四大自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义…

dsa-基础

算法与数据结构 0.概念数据结构复杂度时间复杂度空间复杂度 1. 线性表顺序表(数组)链表单链表双链表循环链表静态链表 顺序表/链表栈顺序栈链式栈 队列顺序循环队列链表队列双端队列 2. 递归递归与栈阶乘例子 3. 矩阵对称矩阵三角矩阵稀疏矩阵 4. 字符串 0.概念 数据结构 逻辑…

dsadas

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

DSDA 简介

参考link&#xff1a;千呼万唤&#xff0c;5G双卡双通到底有多重要&#xff1f;__财经头条 (sina.com.cn)

Java 排序算法:折半插入排序

有关排序的基本内容可以查看以下链接&#xff1a; 折半插入排序_360百科折半插入排序,折半插入排序(Binary Insertion Sort)是对插入排序算法的一种改进。所谓插入排序&#xff0c;就是不断的依次将元素插入前面已排好序的序列中。https://baike.so.com/doc/7028767-7251672.h…

Java排序算法——猴子排序(Bogo Sort)

此排序和之前介绍的三种排序没有任何关系&#xff0c;只是单纯在整理排序算法突然想到曾经看到过关于此排序的描述&#xff0c;现在总结一下。 之前三种排序的传送门开一下&#xff1a; 冒泡排序&#xff1a; Java排序算法——冒泡排序&#xff08;Bubble Sort&#xff09;ht…

java排序算法精讲

排序算法 概要一、冒泡排序概念实现步骤 代码 二、选择排序概念实现步骤 代码 三、插入排序概念实现步骤 代码 四、快速排序概念实现步骤 代码 五、归并排序概念实现步骤 代码 六、堆排序概念实现步骤 代码 总结以二维表表现出各个排序的关系 概要 Java是一种面向对象的编程语言…

Java排序算法(一):冒泡排序

冒泡排序 一、原理二、排序步骤三、实现代码四、复杂度分析 一、原理 冒泡排序是相邻的元素两两比较&#xff0c;把小的元素往前调或者把大的元素往后调&#xff0c;实现最大(小)值排列在一端。 注&#xff1a;相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法 …

十大经典排序算法(Java实现)

排序算法的重要性不言而喻&#xff0c;为了加深对这十种算法的理解&#xff0c;固写此文。 目录 1、冒泡排序&#xff08;Bubble Sort&#xff09;2、选择排序&#xff08;Selection Sort&#xff09;3、插入排序&#xff08;Insertion Sort&#xff09;4、希尔排序&#xff0…

Java排序算法——插入排序(Insertion Sort)

之前总结了交换排序的冒泡排序与选择排序的简单选择排序&#xff0c;这次我们来看看插入排序的简单插入排序~ 往期传送门&#xff1a; 冒泡排序&#xff1a; Java排序算法——冒泡排序&#xff08;Bubble Sort&#xff09;https://blog.csdn.net/babbfqb93/article/details/…

Java排序算法——冒泡排序(Bubble Sort)

冒泡排序是所有排序算法中最简单的一个排序&#xff0c;也是我个人学习的第一个排序方法&#xff0c;在这里重新进行一个总结。 冒泡排序&#xff08;Bubble Sort&#xff09;就如同其名称一样&#xff0c;水中的气泡由于压强的原因所以从下到上其大小也是从小到大&#xff0c…

Java排序算法——插入排序

Java排序算法——插入排序&#xff08;Insertion Sort&#xff09; 传送门 冒泡排序选择排序 简述 插入排序&#xff08;Insertion Sort&#xff09;是一种简单直观的排序算法。它的工作原理是通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前…