C++ 实现计算24点
原理
暴力枚举所有的情况,运算符号4个,加减乘除 + - * / ,整数数字4个(易扩展为5个数或者更多)。所需要枚举的次数:
- 数字顺序:4个数的全排列,4! = 24。
- 运算符号:4个数需要3个符号,每个可选4种,43 = 64。
- 加括号方式:((AB)C)D、(A(BC))D、(AB)(CD)、A((BC)D)、A(B(CD)),共5种。
- 枚举次数 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)
->110010
、A((BC)D)
->110100
、A(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点测试
C++ 实现计算24点相关推荐
- 24点游戏java_使用java编写计算24点游戏程序
初学java,编写了一个计算24点的程序,时间有限,有些粗糙,不过可以使用. //-------------Cal24.java--------------- //计算24点程序 //作者:徒步天下( ...
- c#和javascript分别轻松实现计算24点
24点游戏介绍:给出4个1-9之间的整数(ms我当年玩的时候是用扑克牌),其中每个数字必须且只用一次:任意使用+-*/ ( ),构造出一个表达式,使得最终结果为24,这就是常见的算24点的游戏(我的老 ...
- 计算机公式求时间差公式,24时间差计算公式 excel中计算24小时
excel中计算24小时制时间差 怎样在excel中计算24小时制时间差,在一天之内的小编会,不过不在一天之内外套一个MOD函数,就行了,这样试试 =MOD("0:36"-&quo ...
- 1224 红魔馆的纸牌游戏 (计算24点,dfs)
Description 红魔馆的蕾米莉亚大小姐一天发现人类有一种叫做24点的游戏,于是就带着一副不知哪里弄来的扑克牌到图书馆找帕秋莉玩 24点游戏的规则:从一副牌中随机抽取4张牌,牌的点数为1到13之 ...
- 阿里云云计算 24 SLB的概念
阿里云云计算 24 SLB的概念 参考 https://edu.aliyun.com/lesson_547_21891#_21891
- 使用Scala语言开发GUI界面的计算24点的游戏应用
今年开始学习Scala语言,对它的强大和精妙叹为观止,同时也深深感到,要熟练掌握这门语言,还必须克服很多艰难险阻. 这时,我就在想,如果能有一种方式,通过实际的应用实例,以寓教于乐的方式,引导我们逐步 ...
- 计算24点游戏精化算法剖析
很多人都玩过这个数学味儿很浓的益智游戏:抽出4张扑克牌,牌上的点数代表四个数字,花牌视为1点(有的把J.Q.K分别视为11.12.13点),玩家中谁最先运用加减乘除四则运算,由这四个数计算出24,谁就 ...
- 计算24点的程序及分析过程
计算24点的程序及分析过程 最近正在学习数据结构.和同事闲聊时,聊到了24点的问题(就是给出4个数,然后用加减剩除及括号算出24来),记得前一阵还在网上看了一道24点的题: 5 5 5 1 ,如何算出 ...
- Python之计算24点
完整的代码如下: # -*- coding: utf-8 -*- import itertools#with brackets def with_brackets(lst, ops_lst):for ...
- 用扑克牌计算24点(c语言)
用扑克牌计算24点 题目 答案 注意 参考 题目 答案 #include<stdio.h>float operation(float a,float b,char c) {switch(c ...
最新文章
- 计算机网络有限制,计算机网络中软件限制策略的应用规则有哪些
- ++和+的运算优先级和++i和i++混合用法解析
- php中文乱码问题解决方案
- C++11多线程编程-两个进程轮流打印1~100
- POJ - 1321 棋盘问题
- Category 特性在 iOS 组件化中的应用与管控
- Lambda表达式及应用
- react循环key值_01 React快速入门(一)——使用循环时对于‘key’报错处理
- 计算机文件自动备份到移动硬盘,1个让移动硬盘自动备份的简单方法!
- 增强型绿植植被指数_植被指数计算方法
- yum 报错:Another app is currently holding the yum lock; waiting for it to exit......
- 小技巧:机械键盘使用技巧
- CHD搭建的环境中,解决用户权限的问题
- ABOV单片机KEIL C51编译器程序仿真器OCD-II操作步骤详解
- 大数据来临,商业银行面对合规挑战!
- 计算机网络dce是什么意思,DTE与DCE的解释
- 从零到百亿互网融构展
- 摆脱伪智能困境,全方位解读车联网技术应用
- 模糊C均值聚类以及C实现
- usb hub芯片 android,usb hub芯片GL850G详解