c/c++算法之“24点”经典问题
2013-06-03 20:11
239 查看
24点游戏是一种使用扑克牌来进行的益智类游戏,游戏内容是:从一副扑克牌中抽去大小王剩下52张,任意抽取4张牌,把牌面上的数(A代表1)运用加、减、乘、除和括号进行运算得出24。每张牌都必须使用一次,但不能重复使用。 有些组合有不同种算法,例如要用2,4,6,12四张牌组合成24点,可以有如下几种组合方法: 2 + 4 + 6 + 12 = 24 4 × 6 ÷ 2 + 12 = 24 12 ÷ 4 × (6 + 2) = 24
当然,也有些组合算不出24,如1、1、1、1 和 6、7、8、8等组合。”
本算法的实习过程是通过你循环迭代实现24点的判断,实现过程是以纸牌的张数作为循环的中枢,也即本算法的扩展性较强,可以实现的不只是抽取4张牌,5张,6张等都一样都能实现。
下面以n张牌为例,叙述该算法。
第一步:抽取n张牌当中的任意两张牌,对其做加减乘除运算,将这两个数四则运算过后的结果作为一个数,与其余n-2个数一起构成n-1个数据。
第二步:将得到的n-1组数据,重复第一步的操作。
一二步不断循环,直到n=1,这个时候所有的可能全部计算完毕,输出结果。
代码如下:
如有疑问,欢迎交流
当然,也有些组合算不出24,如1、1、1、1 和 6、7、8、8等组合。”
本算法的实习过程是通过你循环迭代实现24点的判断,实现过程是以纸牌的张数作为循环的中枢,也即本算法的扩展性较强,可以实现的不只是抽取4张牌,5张,6张等都一样都能实现。
下面以n张牌为例,叙述该算法。
第一步:抽取n张牌当中的任意两张牌,对其做加减乘除运算,将这两个数四则运算过后的结果作为一个数,与其余n-2个数一起构成n-1个数据。
第二步:将得到的n-1组数据,重复第一步的操作。
一二步不断循环,直到n=1,这个时候所有的可能全部计算完毕,输出结果。
代码如下:
#include<iostream> #include<string> #include<cmath> using namespace std; const double PRECISION = 1E-6; const int COUNT = 4; const int RESULT = 24; double number[COUNT]; //这里一定要用double,看看第一题的答案就知道为什么了 string expression[COUNT]; //保存表达式 bool Test(int n) { //递归结束 if (n == 1) { if (fabs(number[0] - RESULT) < PRECISION) { cout << expression[0] << endl; return true; } else return false; } //递归过程 for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { double a, b; string expa, expb; a = number[i]; b = number[j]; number[j] = number[n - 1]; expa = expression[i]; expb = expression[j]; expression[j] = expression[n - 1]; expression[i] = '(' + expa + '+' + expb + ')'; number[i] = a + b; if (Test(n - 1)) return true; //减号有两种情况,a-b与b-a expression[i] = '(' + expa + '-' + expb + ')'; number[i] = a - b; if (Test(n - 1)) return true; expression[i] = '(' + expb + '-' + expa + ')'; number[i] = b - a; if (Test(n - 1)) return true; expression[i] = '(' + expa + '*' + expb + ')'; number[i] = a * b; if (Test(n - 1)) return true; //除法也有两种情况,a/b与b/a if (b != 0) { expression[i] = '(' + expa + '/' + expb + ')'; number[i] = a / b; if (Test(n - 1)) return true; } if (a != 0) { expression[i] = '(' + expb + '/' + expa + ')'; number[i] = b / a; if (Test(n - 1)) return true; } //恢复数组 number[i] = a; number[j] = b; expression[i] = expa; expression[j] = expb; } } return false; } int main(void) { for (int i = 0; i < COUNT; i++) { char buffer[20]; int x; cin >> x; number[i] = x; itoa(x, buffer, 10); expression[i] = buffer; } if (Test(COUNT)) cout << "Success" << endl; else cout << "Fail" << endl; system("pause"); return 0; }
如有疑问,欢迎交流
相关文章推荐
- LCS 最长公共子序列(DP经典问题)
- 编码问题查询总结经典文章
- 多线程——引用同步函数解决经典储户银行存钱问题
- 扫雷游戏是一款十分经典的单机小游戏。 问题 H: 扫雷游戏
- 面试技巧:16个经典面试问题回答思路
- 局域网内互访网络共享的六大经典问题
- 16个经典面试问题回答思路
- java蓝桥杯 24点问题
- 0-1背包 (算法竞赛入门经典0-1背包问题)
- 《 C++深度剖析》学习日志十九——经典问题解析二
- C/C++面试笔试中经典的字符串常量内存问题
- 秒杀多线程-一个经典的多线程同步问题
- java经典问题——求年纪
- PAT、PTA 最大子序列类经典问题 7-1 公司利润(20 分)两种方法解答
- 程序备忘录:之十-WEB经典小问题(2004/10/23 13:48)
- 经典:frameset&nbsp;滚动条问题
- UVA - 12124 Assemble(经典二分函数问题)
- 数学概念——F 概率(经典问题)birthday paradox
- 深入解析:分布式系统的事务处理经典问题及模型
- 面试必问的16个经典问题的回答思路