目录

一,24点游戏的规则和分类

二,24点游戏的求解

1,思路1

CSU 1600: Twenty-four point(第(1a)类)

HDU 1427 24点游戏(第(1b)类)

2,思路2

三,特殊组合分析


一,24点游戏的规则和分类

按照运算规则来分类的话,首先24的基本规则:

4个数字可以任意排序,可以任意加括号,运算符+-*/这4个可以选择,但是在选择的时候有2类:

(a)无限制任意选择

(b)必须满足,在计算的过程中不会出现2个数的除法产生分数的情况,在此限制之下运算符可以任选

这2类的区别是,(a)类允许(5-1/5)*5这样的式子,而(b)类不允许

如果按照可能出现的数字来分类的话,有2类:

(1)扑克牌类:1,2,3,4,5,6,7,8,9,10,11,12,13

(2)计算器类:0,1,2,3,4,5,6,7,8,9

所以,交叉分类的话,一共有4种:(1a)(1b)(2a)(2b)

二,24点游戏的求解

思路大致可以分2类,即下面的思路1和思路2

1,思路1

先枚举4个数在表达式中的顺序,24种,然后再枚举计算顺序和运算符,使得4个数化为3个数,

然后再化为2个数,最后化为1个数看是不是24

CSU 1600: Twenty-four point(第(1a)类)

题目:

Description

Given four numbers, can you get twenty-four through the addition, subtraction, multiplication, and division? Each number can be used only once.

Input

The input consists of multiple test cases. Each test case contains 4 integers A, B, C, D in a single line (1 <= A, B, C, D <= 13).

Output

For each case, print the “Yes” or “No”. If twenty-four point can be get, print “Yes”, otherwise, print “No”.

Sample Input

2 2 3 9
1 1 1 1
5 5 5 1

Sample Output

Yes
No
Yes

Hint

For the first sample, (2/3+2)*9=24.

代码:

#include<iostream>
using namespace std;bool ok(double a)
{return a > 23.99999&&a < 24.00001;
}bool ok(double a, double b)
{if (b == 0)return ok(a);return ok(a + b) || ok(a - b) || ok(a*b) || ok(a / b);
}bool ok(double a, double b, double c)
{if (b == 0)return ok(a, c);if (c == 0)return ok(a, b);if (ok((a + b), c) || ok((a - b), c) || ok((a * b), c)|| ok(a / b, c))return true;if (ok(a, b + c) || ok(a, b - c) || ok(a, b * c)|| ok(a, b / c))return true;return false;
}bool ok(double a, double b, double c, double d)
{if (ok(a + b, c, d) || ok(a - b, c, d) || ok(a * b, c, d)|| ok(a / b, c, d))return true;if (ok(a, b + c, d) || ok(a, b - c, d) || ok(a, b * c, d)|| ok(a, b / c, d))return true;if (ok(a, b, c + d) || ok(a, b, c - d) || ok(a, b, c * d)|| ok(a, b, c / d))return true;return false;
}bool ok1(int a, int b, int c, int d)
{return ok(a, b, c, d) || ok(a, c, b, d) || ok(b, a, c, d) || ok(b, c, a, d) || ok(c, a, b, d) || ok(c, b, a, d);
}int main()
{int a, b, c, d;while (cin >> a >> b >> c >> d){if (ok1(a, b, c, d) || ok1(b, c, d, a) || ok1(c, d, a, b) || ok1(d, a, b, c))cout << "Yes" << endl;else cout << "No" << endl;}return 0;
}

HDU 1427 24点游戏(第(1b)类)

题目:

Description

速算24点相信绝大多数人都玩过。就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13)。要求只用'+','-','*','/'运算符以及括号改变运算顺序,使得最终运算结果为24(每个数必须且仅能用一次)。游戏很简单,但遇到无解的情况往往让人很郁闷。你的任务就是针对每一组随机产生的四张牌,判断是否有解。我们另外规定,整个计算过程中都不能出现小数。

Input

每组输入数据占一行,给定四张牌。

Output

每一组输入数据对应一行输出。如果有解则输出"Yes",无解则输出"No"。

Sample Input

A 2 3 6

3 3 8 8

Sample Output

Yes

No

主要的思路就是函数的嵌套。

这个题目我是只用一个字符ch记录所有输入的,空格会自动忽略,0我就人为忽略,遇到0就读取下一个字符,这样,A就是表示1,1就是表示10

代码:

#include<iostream>
using namespace std;int number(char c)
{if (c == 'A')return 1;if (c == 'J')return 11;if (c == 'Q')return 12;if (c == 'K')return 13;if (c == '1')return 10;return c - '0';
}bool ok(int a, int b)
{if (a + b == 24)return true;if (a - b == 24)return true;if (a*b == 24)return true;if (a != 0 && a == 24 * b)return true;return false;
}bool ok(int a, int b, int c)
{if (b == 0){if (ok(a, c))return true;return false;}if (c == 0){if (ok(a, b))return true;return false;}if (ok((a + b), c) || ok((a - b), c) || ok((a * b), c))return true;if (a%b == 0 && ok(a / b, c))return true;if (ok(a, b + c) || ok(a, b - c) || ok(a, b * c))return true;if (b%c == 0 && ok(a, b / c))return true;return false;
}bool ok(int a, int b, int c, int d)
{if (ok(a + b, c, d) || ok(a - b, c, d) || ok(a * b, c, d))return true;if (a%b == 0 && ok(a / b, c, d))return true;if (ok(a, b + c, d) || ok(a, b - c, d) || ok(a, b * c, d))return true;if (b%c == 0 && ok(a, b / c, d))return true;if (ok(a, b, c + d) || ok(a, b, c - d) || ok(a, b, c * d))return true;if (c%d == 0 && ok(a, b, c / d))return true;return false;
}bool ok1(int a, int b, int c, int d)
{if (ok(a, b, c, d) || ok(a, c, b, d) || ok(b, a, c, d) || ok(b, c, a, d) || ok(c, a, b, d) || ok(c, b, a, d))return true;return false;
}int main()
{   char ch;int a, b, c, d;while (cin >> ch){if (ch == '0')cin >> ch;a = number(ch);cin >> ch;if (ch == '0')cin >> ch;b = number(ch);cin >> ch;if (ch == '0')cin >> ch;c = number(ch);cin >> ch;if (ch == '0')cin >> ch;d = number(ch);if (ok1(a, b, c, d)||ok1(b,c,d,a)||ok1(c,d,a,b)||ok1(d,a,b,c))cout << "Yes" << endl;else cout << "No" << endl;}return 0;
}

2,思路2

从4个数里面任取2个数,枚举计算顺序和运算符变成1个数,使得总共化为3个数,然后再化为2个数,最后化为1个数看是不是24

编程之美上面用的就是这类思路。

三,特殊组合分析

有少数的特殊组合,如5 5 5 1,只能(5-1/5)*5得出24,对于b类规则是得不到24的,否则也不用区分a类和b类规则了。

为了方便,将上面的代码略微修改变成如下代码:

#include<iostream>
using namespace std;bool ok(int a, int b)
{if (a + b == 24 || a - b == 24 || a*b == 24 || a != 0 && a == 24 * b){cout << a << " " << b << endl;return true;}return false;
}bool ok(int a, int b, int c)
{if (b == 0){if (ok(a, c))return true;return false;}if (c == 0){if (ok(a, b))return true;return false;}if (ok((a + b), c) || ok((a - b), c) || ok((a * b), c))return true;if (a%b == 0 && ok(a / b, c))return true;if (ok(a, b + c) || ok(a, b - c) || ok(a, b * c))return true;if (b%c == 0 && ok(a, b / c))return true;return false;
}bool ok(int a, int b, int c, int d)
{if (ok(a + b, c, d) || ok(a - b, c, d) || ok(a * b, c, d))return true;if (a%b == 0 && ok(a / b, c, d))return true;if (ok(a, b + c, d) || ok(a, b - c, d) || ok(a, b * c, d))return true;if (b%c == 0 && ok(a, b / c, d))return true;if (ok(a, b, c + d) || ok(a, b, c - d) || ok(a, b, c * d))return true;if (c%d == 0 && ok(a, b, c / d))return true;return false;
}bool ok1(int a, int b, int c, int d)
{if (ok(a, b, c, d) || ok(a, c, b, d) || ok(b, a, c, d) || ok(b, c, a, d) || ok(c, a, b, d) || ok(c, b, a, d))return true;return false;
}int main()
{int a, b, c, d;while (scanf("%d %d %d %d",&a,&b,&c,&d)){if (ok1(a, b, c, d) || ok1(b, c, d, a) || ok1(c, d, a, b) || ok1(d, a, b, c))cout << "Yes" << endl;else cout << "No" << endl;}return 0;
}

下面分析(a)和(b)的区别,到底有多少例子(以下简称必出现分数例子),是在(b)类规则下是计算不出结果的,在(a)类下是可以的。

比如1,5,5,5就是一个特殊例子,不难发现,这样的例子只有6种情况:

(a-b/c)*d 和 (b/c-a)*d 和 (a+b/c)*d 和   d/(a-b/c)和 d/(b/c-a) 和 d/(a+b/c)

以下将可以用上述6种方法计算出来的例子称为可出现分数例子

必出现分数例子,肯定都是可出现分数例子,但是反过来未必

比如9,9,6,2,(9+9-6)*2=24,(2+6/9)*9=24

所以下面讨论,对于扑克牌类,可出现分数例子有哪些,其中又有哪些是必出现分数例子。

将6种情况化成整型方程:

(a*c-b)*d=24*c 和 (b-a*c)*d=24*c 和 (a*c+b)*d=24*c 和 c*d=24*(a*c-b) 和 c*d=24*(b-a*c) 和 c*d=24*(a*c+b)

求出所有可出现分数例子的代码:

#include<iostream>
using namespace std;bool ok(int a, int b, int c, int d)
{
if ((a*c - b)*d == 24 * c || (b - a*c)*d == 24 * c || (a*c + b)*d == 24 * c)return true;
if (c*d == 24 * (a*c - b) || c*d == 24 * (b - a*c) || c*d == 24 * (a*c + b))return true;
return false;
}int main()
{for (int a = 1; a <= 13; a++)for (int b = 1; b <= 13; b++)for (int c = 1; c <= 13; c++)for (int d = 1; d <= 13; d++)if (b%c  && ok(a, b, c, d))cout << a << " " << b << " " << c << " " << d << endl;return 0;
}

输出:

1 1 2 12
1 2 3 8
1 2 4 12
1 3 2 12
1 3 4 6
1 3 6 12
1 4 3 8
1 4 6 8
1 4 8 12
1 5 3 9
1 5 4 6
1 5 6 4
1 5 8 9
1 5 10 12
1 6 4 12
1 6 8 6
1 6 9 8
1 6 12 12
1 7 5 10
1 7 6 4
1 7 8 3
1 7 12 10
1 8 6 8
1 8 12 8
1 9 6 12
1 9 8 3
1 9 12 6
1 10 6 9
1 10 8 6
1 10 12 4
1 11 3 9
1 11 8 9
1 11 12 2
1 11 13 13
1 12 8 12
1 12 9 8
1 13 11 11
1 13 12 2
2 2 3 9
2 2 5 10
2 2 11 11
2 2 13 13
2 3 2 12
2 4 6 9
2 4 10 10
2 5 2 12
2 5 3 8
2 6 4 12
2 6 9 9
2 7 3 8
2 7 4 6
2 8 12 9
2 9 4 6
2 9 6 12
2 10 4 12
2 10 6 8
2 10 7 7
2 11 6 4
2 12 8 12
2 13 6 4
2 13 8 9
3 1 3 9
3 2 6 9
3 3 5 10
3 3 7 7
3 3 9 9
3 4 12 9
3 5 2 12
3 6 10 10
3 7 2 12
3 8 3 8
3 9 5 5
3 9 11 11
3 10 3 8
3 10 4 12
3 11 4 6
3 13 4 6
4 4 3 9
4 4 5 5
4 4 7 7
4 7 2 12
4 8 5 10
4 8 6 9
4 8 10 5
4 9 2 12
4 11 3 8
4 12 9 9
4 13 3 8
5 1 5 5
5 2 10 5
5 7 3 9
5 9 2 12
5 11 2 12
5 11 7 7
5 13 5 10
6 6 5 5
6 10 3 9
6 11 2 12
6 12 10 5
6 13 2 12
7 11 5 5
7 13 2 12
7 13 3 9

一共103组

再看着其中有多少组是必出现分数例子。

可以把上面的2个代码整合起来,也可以把上面的输出输入到第1个程序里面判断。

最后可以得到,必出现分数例子只有如下17个(其中有2个是重复的)

1 3 4 6     ——— 6/(1-3/4)
1 5 4 6     ——— 6/(5/4-1)
1 5 6 4     ———4/(1-5/6) (这2个是重复的)
1 6 8 6     ——— 6/(1-6/8)
1 12 8 12  ———12/(12/8-1)
2 2 11 11    ——— (2+2/11)*11
2 2 13 13     ——— (2-2/13)*13
2 4 10 10   ———(2+4/10)*10
2 10 7 7   ———(2+10/7)*7
3 3 7 7   ——— (3+3/7)*7
3 5 2 12  ——— 12/(3-5/2)
3 8 3 8    ——— 8/(3-8/3)
4 4 7 7    ——— (4-4/7)*7
5 1 5 5    ——— (5-1/5)*5
5 2 10 5  ——— (5-2/10)*5
5 11 7 7 ——— (5-11/7)*7
7 11 5 5  ———(7-11/5)*5

puzzle(0151)《24点》相关推荐

  1. c#拼图碎片形状_使用神经网络解决拼图游戏

    在一个排列不变性的数据上神经网络是困难的.拼图游戏就是这种类型的数据,那么神经网络能解决一个2x2的拼图游戏吗? 什么是置换不变性(Permutation Invariance)? 如果一个函数的输出 ...

  2. 用神经网络解决拼图游戏

    在一个排列不变性的数据上神经网络是困难的.拼图游戏就是这种类型的数据,那么神经网络能解决一个2x2的拼图游戏吗? 什么是置换不变性(Permutation Invariance)? 如果一个函数的输出 ...

  3. Eight puzzle --HOJ 11918

    1.题目类型:模拟.哈希表.BFS. 2.解题思路:(1)模拟Eigh Puzzle的变换方式,并记录在数组中 :(2)由于变换的最终结果相同,所以采用反向的BFS遍历所有情况,并记录所有情况:(3) ...

  4. Java黑皮书课后题第8章:*8.24(检验数独的解决方案)程序清单8-4通过检测棋盘上的每个数字是否是有效的,从而检验一个解决方案是否是有效的。重写该程序,通过检验是否每行、每列、每个小方盒中具有

    *8.24(检验数独的解决方案)程序清单8-4通过检测棋盘上的每个数字是否是有效的,从而检验一个解决方案是否是有效的.重写该程序 题目 题目描述 程序清单8-4 破题 代码 题目 题目描述 *8.24 ...

  5. poj 3678 Katu Puzzle(2-sat)

    Description Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a ...

  6. 【UVA - 227】Puzzle (模拟,水题)

    题干: Puzzle  A children's puzzle that was popular 30 years ago consisted of a 5x5 frame which contain ...

  7. 吴昊品游戏核心算法 Round 18 —— 吴昊教你玩Zen Puzzle Garden

    如果你认为无法因为玩一个电脑游戏而达到精神的顿悟,你可能是正确的.不过你完全可以试着解决一个禅宗花园发生的难题,从而达到静心的精神状态.   这个游戏是获得2003年独立游戏节提名的精品游戏,在注重游 ...

  8. puzzle(004.1)日历拼图

    目录 一,规则 二,每日拼图 2022年2月 2022年3月 竖条下滑问题 2022年4月 2022年5月 2022年6月 三,术语 四,启发式搜索策略 1,数独 2,策略一 3,策略二 4,策略三 ...

  9. puzzle(1311)点亮所有的灯

    目录 一,点亮所有的灯 二,子问题性质 三,术语定义 四,解空间的结构 五,全局状态.全局操作的关系 六,编程求解 POJ 3279 Fliptile POJ 1222 EXTENDED LIGHTS ...

最新文章

  1. DLL技术应用04 - 零基础入门学习Delphi47
  2. JavaWeb编程(十)Json语句
  3. C语言函数手册:c语言库函数大全|C语言标准函数库|c语言常用函数查询
  4. Linux uptime指令
  5. Linux / pthread_create() 函数所使用的线程函数为什么必须是静态函数?
  6. java 局部性原理_程序局部性原理
  7. 新书《深入理解Kafka:核心设计与实践原理》上架,感谢支持~
  8. 数学之史:微积分的发明——变量数学的巨人之争
  9. 拥抱 Android Studio 之五:Gradle 插件开发
  10. OpenCV-人像—酷感冷艳滤镜
  11. mongodb启动很慢:[initandlisten] found 1 index(es) that
  12. CorelDRAWX4的VBA插件开发(六)录制宏与调试
  13. PGP加密并签名邮件 实验
  14. bat的使用技巧汇总
  15. 离线安装docker
  16. iOS/Android 微信及浏览器中唤起本地APP
  17. 计算机论文的致谢部分写什么,毕业论文的致谢部分怎么写?
  18. 博士毕业论文英文参考文献换行_如何赏心悦目的翻译英文文献全文
  19. 计算机如何查看网络延时,电脑上怎么看网络丢包?网络延时查看方法
  20. js验证银行卡号,并自动识别银行信息。js验证手机码。js验证数字

热门文章

  1. docker镜像指定安装源_详解如何修改docker pull镜像源
  2. revit服务器维护,Revit server是什么?Revit Server 管理有问题,谁来解决、怎么解决?...
  3. Xtrabackup使用指南 InnoDB数据备份工具
  4. 最简单粗暴的蓝牙耳机选购技巧,盲选不踩雷五款品牌推荐
  5. 天数转换成具体有多少年多少月多少天
  6. html word页面展示,word文档怎样调页面
  7. HHTC第十二届程序设计竞赛
  8. 露营不在朋友圈,快乐在诗和远方
  9. GOOGLE怎么用?
  10. 如何删除word中的长横线(由三个减号---自动生成)