蓝桥杯 试题 算法训练 24点 C++ 详解

article/2025/10/24 6:43:04

问题描述:

  24点游戏是一个非常有意思的游戏,很流行,玩法很简单:给你4张牌,每张牌上有数字(其中A代表1,J代表11,Q代表12,K代表13),你可以利用数学中的加、减、乘、除以及括号想办法得到24,例如:
  ((A*K)-J)*Q等价于((1*13)-11)*12=24
  加减乘不用多说了,但除法必须满足能整除才能除!这样有一些是得不到24点的,所以这里只要求求出不超过24的最大值。

输入格式:

  输入第一行N(1<=N<=5)表示有N组测试数据。每组测试数据输入4行,每行一个整数(1到13)表示牌值。

输出格式:

  每组测试数据输出一个整数,表示所能得到的最大的不超过24的值。

样例输入:

3
3
3
3
3
1
1
1
1
12
5
13
1

样例输出:

24
4
21


前言:

参考解法:

蓝桥杯 算法训练 24点_陆小路-1的博客-CSDN博客

原博客讲得很详细,评论区也有不少问题解答。

(仅需解法的 同学/读者 直接跳转 即可)

这里我还是只讲一下我的解题过程(主要是错误的原因)。

临近省赛,这篇文章就再小小总结一下目前做过的《算法训练》题目。

(删了一大段感慨的话)

笔者,也是要去刷一刷官网的真题才行……


开始:

题做到这里,相信大家已经对一些算法(dp,dfs)有了一定的了解。

已经做过的题目:

《印章》:dp(动态规划),最终结果由上一步结果推导出。

《拿金币》:同上。

《无聊的逗》:经典的dfs算法。

《礼物》:找规律。

《跳马》:dfs(深度优先搜索), bfs(宽度优先搜索) 都能解。

《数的潜能》:找规律。

《娜神平衡》:dfs + dp?

《粘木棍》:dfs

《车的放置》:dfs

《24点》:dfs

其中,《印章》《拿金币》《礼物》《数的潜能》就不讲了,随机应变吧。

笔者浅浅总结一下这些题所用dfs的区别。

《无聊的逗》,经典的dfs,利用每层递归的三种操作,遍历出所有的情况。但仅限于对当前"对象"进行操作。

《跳马》,经典的dfs,利用每层递归的两种操作,遍历出所有的情况。但也仅限于对当前"对象"进行操作。

《娜神平衡》,同为dfs操作,但它却可以实现:对一些对象进行选择(每层内部都有一个for循环遍历所有对象)。不难发现,其依据是用int或bool数组存放对象的状态

《粘木棍》,……

《车的放置》,……

《24点》,而本题的dfs操作又有不同,它是每层循环都挑出两个数,对齐进行(加减乘除)。


笔者水平有限,对这些dfs的总结为:

橙色dfs的作用:对某个对象进行不同的操作,适用于穷举"按顺序"的所有情况。

例:给定ABCDEFG……不同的物品,每个物品都可以拿或不拿,请穷举所有情况。

黄色dfs的作用:对某个对象进行不同的操作,适用于穷举"不按顺序"的所有情况。

例:给定ABCDEFG……不同的物品,请穷举所有组合(ABCDEGF……)。

绿色dfs的作用:对两个对象进行不同的操作,适用于穷举"两两配对?"的所有情况。

其实跟黄色dfs差不多,,,


接下来看题,其本质就是问:对4个数进行加减乘除的操作,怎么得到小于等于24最大的数?

一开始我是延续上几题《娜神平衡》dfs想法,但提交程序后正确率最高只有60%。

上网查了以后发现存在优先级和分配律的问题,

按自己的方式,笔者写的检查错误的代码如下:

#include<iostream>
using namespace std;//分组数量
int N = 0;//数据:最多5组,每组4个
int Date[5][4] = { 0 };//标记数据状态:false:未被使用;true:已使用
int Date_index[5][4] = { 0 };int result[6] = { 0 };//检查数据是否"全部"都已使用 - 作为边界条件
bool func01(int row)
{for (int i = 0; i < 4; i++){if (!Date_index[row][i])return false;}return true;
}//将数字转"字符"返回
string func02(int sum)
{string s = "";do{s += '0' + sum % 10;sum /= 10;} while (sum > 0);reverse(s.begin(), s.end());return s;
}string S;void func(const int row, int sum = 0, bool bol = false, string s = "", int x = 0)
{x++;//若结果已为最大值,无需继续if (result[row] == 24)return;//该row组数据全部用上 - (更新)结束if (func01(row)){s += " = " + func02(sum);if (result[row] < sum && sum <= 24){result[row] = sum;S = s;}return;}//第一次调用时,填充任一数字作为第一位(防止存在0 * 0导致莫名去除了一些数据)if (!bol){for (int i = 0; i < 4; i++){sum = Date[row][i];Date_index[row][i] = x;//标记已使用s = func02(Date[row][i]);func(row, sum, true, s, x);Date_index[row][i] = 0;//回溯}}//第二/三/四次调用else{for (int i = 0; i < 4; i++){if (!Date_index[row][i]){Date_index[row][i] = x;//标记已使用string temp;int x1 = sum + Date[row][i];//加temp = s + " + " + func02(Date[row][i]);func(row, x1, true, temp, x);int x2 = sum - Date[row][i];//减temp = "|" + s + " - " + func02(Date[row][i]) + "|";x2 = x2 > 0 ? x2 : -x2;func(row, x2, true, temp, x);int x3 = sum * Date[row][i];//乘temp = "(" + s + ")" + " * " + func02(Date[row][i]);func(row, x3, true, temp, x);if (Date[row][i] != 0 && sum % Date[row][i] == 0){temp = "(" + s + ")" + " / " + func02(Date[row][i]);func(row, sum / Date[row][i], true, temp, x);//除}else if (sum != 0 && Date[row][i] % sum == 0){temp = func02(Date[row][i]) + " / " + "(" + s + ")";func(row, Date[row][i] / sum, true, temp, x);//除}Date_index[row][i] = 0;//回溯}}}
}int n = 1;//n组测试数据 
int nums[4];//4个数字 
int ans;//不超过24的最大值 //函数功能: 在有n个数的数组nums中	寻找最大的不超过24的值。
void f(int nums[], int n) {//只有1个数时,比较最大值 if (n == 1) {//如果该数不大于24,更新最大值 if (nums[n - 1] <= 24) {ans = ans < nums[n - 1] ? nums[n - 1] : ans;}return;}//遍历两个数的组合 for (int i = 0; i < n - 1; i++) {for (int j = i + 1; j < n; j++) {int a = nums[i], b = nums[j];nums[j] = a + b;		//加法和乘法具有交换律 nums[i] = nums[n - 1];f(nums, n - 1);nums[j] = a * b;nums[i] = nums[n - 1];f(nums, n - 1);nums[j] = a - b;		//减法和除法不具有交换律 nums[i] = nums[n - 1];f(nums, n - 1);nums[j] = b - a;nums[i] = nums[n - 1];f(nums, n - 1);if (b != 0 && a % b == 0) {		//除数不能为0 nums[j] = a / b;nums[i] = nums[n - 1];f(nums, n - 1);}if (a != 0 && b % a == 0) {nums[j] = b / a;nums[i] = nums[n - 1];f(nums, n - 1);}nums[i] = a;    //恢复现场 nums[j] = b;}}
}int main()
{输入数据//cin >> N;//for (int i = 0; i < N; i++)//	for (int j = 0; j < 4; j++)//	{//		cin >> Date[i][j];//	}对每层进行运算//for (int i = 0; i < N; i++)//	func(i);输出结果//for (int i = 0; i < N; i++)//	cout//	<< S << endl//	//<< result[i] << endl//	;int cnt = 0;for (int a = 1; a <= 13; a++){for (int b = a; b <= 13; b++){for (int c = b; c <= 13; c++){for (int d = c; d <= 13; d++){Date[0][0] = a;Date[0][1] = b;Date[0][2] = c;Date[0][3] = d;func(0);cout << S << endl;ans = 0;nums[0] = a;nums[1] = b;nums[2] = c;nums[3] = d;f(nums, 4);cout << " -> " << ans << endl;if (ans != result[0])system("pause>nul");S = "";result[0] = 0;cnt++;}}}}cout << cnt << endl;return 0;
}

部分运行截图如下:

每次都会在 = 结果 -> 结果 不同的时候暂停。

肉眼可得:若按最朴素的黄色dfs,对:1 1 1 9 得到的结果只有(1+1)*9+1=19最大。

但我们仍易得出:最大应该是(1 + 1) * (1 + 9) = 20,

可是原先的dfs思路是无法做到:将前后两个各自相加的。只能以(之前得到的数)一个数为基准,然后对其不断 加减乘除……

所以又需"升级"一下dfs解法。

具体解法看上面提到的博客,我就不详写了。


结束:

最近实在比较忙,还得准备省赛,抽空写文章小小总结一下dfs,分享 + 加深  自己的理解。

……


http://chatgpt.dhexx.cn/article/2jAUbM3p.shtml

相关文章

24点游戏(python)

24点游戏&#xff08;python&#xff09; 一、题目要求 1.问题描述&#xff1a; 24点游戏是经典的纸牌益智游戏。常见游戏规则&#xff1a; 从扑克中每次取出4张牌。使用加减乘除&#xff0c;第一个能得出24者为赢。&#xff08;其中&#xff0c;J代表11&#xff0c;Q代表12&a…

用java实现24点游戏

前言 用java实现24点游戏 Welocome to Xiang’s world~ 题目ღ( &#xff65;ᴗ&#xff65; ) 24点游戏是经典的纸牌益智游戏。 常见游戏规则&#xff1a; 从扑克中每次取出4张牌。使用加减乘除&#xff0c;第一个能得出24者为赢。&#xff08;其中&#xff0c;J代表11&am…

C++ 实现计算24点

原理 暴力枚举所有的情况&#xff0c;运算符号4个&#xff0c;加减乘除 - * / &#xff0c;整数数字4个&#xff08;易扩展为5个数或者更多&#xff09;。所需要枚举的次数&#xff1a; 数字顺序&#xff1a;4个数的全排列&#xff0c;4! 24。运算符号&#xff1a;4个数需要…

计算机上的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…