来源:http://www.xici.net/d190569991.htm

经典二十四点程序算法 --叶 宏

一、概述
算24点:任意给定四个整数,用加、减、乘、除以及适当的括号连接,无论顺序,使计算结果为24,也可能根本就无解。如何用程序简单实现找到算式是程序初学者关注的问题,百度上可以搜到许多这样的文章,有递归法、回溯法、穷举法。但穷举法最为简单、易于理解。
二、算法
穷举法就是把四个数字的所有运算式进行尝试计算,要设法把所有排列一点不差地穷举出,一、是四个整数位置的排列,用0,1,2,3表示位置,排列是不能重复的,所以有P(4,4)种情况,即4!=4*3*2*1=24种;二、是三个运算符的变化,每个运算符为+-*/ ,可以相同,所以,有4*4*4=64种; 三、三个运算符的优先级,就是括号位置的变化,可能性为P(3,3)-1=6-1=5种;所以,表达式的可能性为:24*64*5=7680种,C语言程序把这么多表达式都计算一遍,几乎不到1毫秒毫不费劲, 可见电脑的运行速度之快。
   四个数位置的排列,可用四重循环实现,四个循环变量i1,i2,i3,i4对应数组下标的变化,
不许它们之间相等,四个数放在数组v[0]、v[1]、v[2]、v[3]:
       for (int i1=0;i1<4;i1++)
        for (int i2=0;i2<4;i2++)                
           if (i2!=i1)               //  循环变量不许相同
           for (int i3=0;i3<4;i3++)
              if (i3!=i2 && i3!=i1)         //  循环变量不许相同,&& 是“并且”
              for (int i4=0;i4<4;i4++)
                 if (i4!=i3 && i4!=i2 && i4!=i1)   //  循环变量不许相同
                  {
                    //  v[i1],v[i2],v[i3],v[i4] 就是排列的结果,共有4!=24 种
                  }
   三个运算符的变化,可用三重循环实现,三个循环变量 f1,f2,f3对应位置的变化,允许相同,运算符放在数组op[0]、op[1]、op[2]、op[3]中:
        for (int f1=0;f1<4;f1++)      // 三重循环对运算符穷举
          for (int f2=0;f2<4;f2++)
            for (int f3=0;f3<4;f3++)  // 运算符 f1,f2,f3
                 {
                   // op[f1],op[f2],op[f3]就是排列结果,共有4*4*4=64 种                      
                 }
   上面两种排列组合后,四个数及运算符排列顺序就是:
    v[i1],op[f1],v[i2],op[f2],v[i3],op[f3],v[i4]
但运算符有优先级,一般是用括号表示。我们可以规定运算符的优先级来代替括号。设四张牌为a、b、c、d,运算符为①、②、③,表达式为a ① b ② c ③ d。 这3个运算符的运算顺序有3!=6种,分别是:
1.①②③    2.①③②    3.②①③    4.②③①    5.③①②    6.③②①
等价的表达式分别是:
1.((a①b②)c③)d          2.(a①b)②(c③d)            3.(a①(b②c))③d
4.a①((b②c)③d)        5.(a①b)②(c③d)            6. a①(b②(c③d))
显然,2和5是相同的,因此只考虑5种情况。这样,括号的问题就解决了。为了简单起见,这五种情况未用循环,大大减化了程序的复杂性,更易于理解。

对这组排列逐一进行运算,看是否是24,就可以得到最终所有式子了。在运算过程中除法的特殊性——除数不能为零。因为可能会用到除法,所以要考虑精度问题,这里通过结果减去24取绝对值与一个接近0的小数(如0.001)比较,如小于它,即可判定结果是24。

#include "stdio.h"                         // 输入输出定义
double  cal(double a,double b,int op)      // op: 0:+,1:-,2:*,3:/
{switch (op)                        // +-x/ 运算{case 0:  return(a+b);case 1:  return(a-b);case 2:  return(a*b);}if (b==0.0)                       //  分母为0return(999.0);elsereturn(a/b);
}
bool    isEqual(double d1,double d2)     // 两个浮点数是否近似相等
{double d=d1-d2;if (d<0)d=-d;                        // 求绝对值return(d<=0.001);
}
void   D24(int v0,int v1,int v2,int v3)          // 穷举法求24点
{char op[4]={'+','-','*','/'};             //  +:0  -:1 *:2  /:3int v[4];                                 // 输入四整数v[0]=v0; v[1]=v1;v[2]=v2; v[3]=v3;
//-----------四重循环开始穷举四个数字的位置: 4!=24 种--------------------------int count=0;                              // 计数成功次数for (int i1=0;i1<4;i1++)for (int i2=0;i2<4;i2++)                 // 四重循环对四个数穷举if (i2!=i1)for (int i3=0;i3<4;i3++)if (i3!=i2 && i3!=i1)for (int i4=0;i4<4;i4++)if (i4!=i3 && i4!=i2 && i4!=i1){
//-----------三重循环开始穷举三个运算符: 4X4X4=64 种---------------------------for (int f1=0;f1<4;f1++)      // 三重循环对运算符穷举for (int f2=0;f2<4;f2++)for (int f3=0;f3<4;f3++)  // 运算符 f1,f2,f3{                       // 对运算优先级直接列举(5种)
//-----------未用循环,直接穷举三个运算符的优先级: 3!-1=5种--------------------double t1,t2,t3;      // 存放计算的中间值// 第1种情况  ((a 。b)。c)。d  :t1=cal(v[i1],v[i2],f1);t2=cal(t1,v[i3],f2);t3=cal(t2,v[i4],f3);if (isEqual(t3,24))    // 运算后是否为24{char *fs="((%d%c%d)%c%d)%c%d=24\\n";printf(fs,v[i1],op[f1],v[i2],op[f2],v[i3],op[f3],v[i4]);count++;}// 第2种情况(a 。b)。(c。 d) 开始计算 :t1=cal(v[i1],v[i2],f1);t2=cal(v[i3],v[i4],f3);t3=cal(t1,t2,f2);if (isEqual(t3,24))      // 运算后是否为24{char *fs="(%d%c%d)%c(%d%c%d)=24\\n";printf(fs,v[i1],op[f1],v[i2],op[f2],v[i3],op[f3],v[i4]);count++;}// 第3种情况 (a。(b。c))。d  开始计算 :t1=cal(v[i2],v[i3],f2);t2=cal(v[i1],t1,f1);t3=cal(t2,v[i4],f3);if (isEqual(t3,24))    // 运算后是否为24{char *fs="(%d%c(%d%c%d))%c%d=24\\n";printf(fs,v[i1],op[f1],v[i2],op[f2],v[i3],op[f3],v[i4]);count++;}// 第4种情况  a。((b。c)。d ) 开始计算:t1=cal(v[i2],v[i3],f2);t2=cal(t1,v[i4],f3);t3=cal(v[i1],t2,f1);if (isEqual(t3,24))    // 运算后是否为24{char *fs="%d%c((%d%c%d)%c%d)=24\\n";printf(fs,v[i1],op[f1],v[i2],op[f2],v[i3],op[f3],v[i4]);count++;}// 第5种情况 a。(b。(c。d)) 开始计算:t1=cal(v[i3],v[i4],f3);t2=cal(v[i2],t1,f2);t3=cal(v[i1],t2,f1);if (isEqual(t3,24))    // 运算后是否为24{char *fs="%d%c(%d%c(%d%c%d))=24\\n";printf(fs,v[i1],op[f1],v[i2],op[f2],v[i3],op[f3],v[i4]);count++;}}}
//-------------- 穷举结束: 共 24*64*5=7680 种表达式 ---------------------------if (count==0)printf("\\n%d,%d,%d,%d 不能算出24.",v0,v1,v2,v3);elseprintf("\\n共找到算式 %d 条.",count);
}
void    main()
{int v0,v1,v2,v3;printf("输入四个整数: ");scanf("%d %d %d %d",&v0,&v1,&v2,&v3);D24(v0,v1,v2,v3);getchar();getchar();
}

经典二十四点程序算法相关推荐

  1. 经典二十四点程序游戏

    经典二十四点程序算法 来源:http://www.xici.net/d190569991.htm 一.概述 算24点:任意给定四个整数,用加.减.乘.除以及适当的括号连接,无论顺序,使计算结果为24, ...

  2. OpenCV学习(二十) :分水岭算法:watershed()

    OpenCV学习(二十) :分水岭算法:watershed() 参考博客: OpenCV-分水岭算法 图像处理--分水岭算法 OpenCV学习(7) 分水岭算法(1) Opencv分水岭算法--wat ...

  3. CCF201903-2 二十四点(100分)【表达式计算】

    问题链接:CCF201903-2 二十四点 问题分析: 表达式计算问题,关键是对输入流进行处理,需要考虑表达式中运算符的优先级.简单的逻辑,用穷举法就可以了. 用Python语言来实现的话,问题就简单 ...

  4. 『牛角书』基于JS实现的鸿蒙游戏——二十四点纸牌

    目录 前言 概述 正式开始 一.创建项目 二.编码 1.项目结构 2.实现思路 3.主要代码块 三.页面及功能展示 1.运算正确 2.运算错误 3.换一批及重置 本人项目仓库链接 前言 相信大家都有玩 ...

  5. C语言 解决CCF 二十四点问题

    利用 C 语言 解决 CCF题库中的二十四点问题 特别致谢:原博主程序 编译环境: IDE:DEV-C++ 语言:C语言 CCF CSP官方往年题库链接点我进入 1. 题目如下: 解题思路: 此题难点 ...

  6. 从LeetCode 679. 24 Game--C++ 解法--二十四点 到穷举24点所有可能性-24点大全

    从LeetCode 679. 24 Game–C++ 解法–二十四点 到穷举24点所有可能性 此文首发于我的个人博客:zhang0peter的个人博客 LeetCode题解文章分类:LeetCode题 ...

  7. CCF-CSP 201903-2 二十四点 Python语言 模拟栈实现

    项目场景: 二十四点问题本质是处理表达式,一提到处理表达式第一反应大概就是使用栈来处理,虽然网上大部分使用python语言处理二十四点问题都是利用强大的eval()函数,但我仍然想要使用python的 ...

  8. CCF CSP201903-2二十四点

    CCF CSP201903-2二十四点 题目描述 要点分析 此题是典型的中缀表达式的求解问题, 可以采用堆栈求解. 具体计算思路: 使用两个栈, num用于存储操作数, opt用于存储操作符 从左往右 ...

  9. CCF 201903-2 二十四点 用栈模拟简单计算器

    二十四点 来源:CCF 背景 二十四点是一款著名的纸牌游戏,其游戏的目标是使用 3 个加减乘除运算使得 4张纸牌上数字的运算结果为 24. 题目 定义每一个游戏由 4 个从 1-9 的数字和 3 个四 ...

  10. 「csp模拟试题 201903-2」二十四点 C/C++ 100分

    目录 题目 输入输出样例 题解思路 题解源码(c/c++) 题目 :二十四点 [问题描述] 定义每一个游戏由 4 个从 1-9 的数字和 3 个四则运算符组成,保证四则运算符将数字两两隔开,不存在括号 ...

最新文章

  1. 机器学习如何帮助企业高效地管理数据?
  2. SQL SERVER 分区表的总结--一些疑问的总结
  3. swift3.0 Runtime 增加属性
  4. 2字节取值范围_5G NR 下行同步SSB(2)—PSS和SSS的用途
  5. 比国内贵3000元!小米11 Ultra将于5月11日登陆欧洲市场
  6. Zabbix官方文件Zabbix图形树
  7. centos6.4用cloudera manager安装hadoop2.0.0-cdh4.3.0集群(二)
  8. 金庸群侠传 3小时爆机
  9. 【雷达与对抗】【2004.05】合成孔径雷达X波段发射机和频率分配单元的设计与实现
  10. 浏览量(PV)、访客数(UV)、访问次数、跳出率
  11. 图文详解优麒麟系统安装教程(建议收藏)
  12. 中移物联网在车联网场景的 TiDB 探索和实现
  13. Linux远程联机服务(二)——Rsh服务器安装与使用详解
  14. EChat(简易聊天项目)四、模拟强制下线
  15. 绿豆pro前端APP源码v5.1.7编译教程,后端配置全开源安装搭建全图文操作萝卜白菜app通用说明带视频教程_多啦咪
  16. 震动传感器(模拟和数字)
  17. Hadoop与workflow入门
  18. vmware虚拟主机使用大于4G的启动盘安装win7至win10的iso文件,无法启动安装的解决方法。
  19. win10下安装office2019
  20. 用python将GBK编码文件转为UTF-8编码文件

热门文章

  1. 2G GSM基站的工作原理
  2. 计算机的网络命令大全,windows常用网络命令图文详解
  3. 免费OA办公系统评测 到底哪个适合本公司?
  4. 登陆豆瓣显示服务器开小差,豆瓣打不开
  5. pyecharts可视化画3D动态地球仪,世界地图,中国地图。
  6. c语言oj质数还是合数,求数据帝帮忙测试一下代码,已被南洋理工大学的oj搞蒙.....
  7. 硬件检测相关工具大全
  8. 【UE4_蓝图】录制麦克风声音/系统声音并输出保存WAV文件
  9. HTML将广告关闭的JS代码,js实现可关闭的对联对联广告代码广告效果代码
  10. 2015游戏蛮牛——蛮牛杯第四届开发者大赛 创见VR未来开启报名