大家好,欢迎来到IT知识分享网。
目录
CSU 1600: Twenty-four point(第(1a)类)
一,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
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; }
力扣 679. 24 点游戏(第(2a)类)
给定一个长度为4的整数数组 cards
。你有 4
张卡片,每张卡片上都包含一个范围在 [1,9]
的数字。您应该使用运算符 ['+', '-', '*', '/']
和括号 '('
和 ')'
将这些卡片上的数字排列成数学表达式,以获得值24。
你须遵守以下规则:
- 除法运算符
'/'
表示实数除法,而不是整数除法。- 例如,
4 /(1 - 2 / 3)= 4 /(1 / 3)= 12
。
- 例如,
- 每个运算都在两个数字之间。特别是,不能使用
“-”
作为一元运算符。- 例如,如果
cards =[1,1,1,1]
,则表达式“-1 -1 -1 -1”
是 不允许 的。
- 例如,如果
- 你不能把数字串在一起
- 例如,如果
cards =[1,2,1,2]
,则表达式“12 + 12”
无效。
- 例如,如果
如果可以得到这样的表达式,其计算结果为 24
,则返回 true
,否则返回 false
。
示例 1:
输入: cards = [4, 1, 8, 7] 输出: true 解释: (8-4) * (7-1) = 24
示例 2:
输入: cards = [1, 2, 1, 2] 输出: false
提示:
cards.length == 4
1 <= cards[i] <= 9
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); } class Solution { public: bool judgePoint24(vector<int>& cards) { int a=cards[0],b=cards[1],c=cards[2],d=cards[3]; return ok1(a, b, c, d) || ok1(b, c, d, a) || ok1(c, d, a, b) || ok1(d, a, b, c); } };
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
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/141542.html