经典游戏--24点--c++代码实现和总体思路(简单暴力向)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

经典游戏--24点--c++代码实现和总体思路(简单暴⼒向)
24点
24点是⼀个⾮常经典的游戏,从扑克牌⾥抽4张牌,其中J=11,Q=12,K=13,然后经过+,-,*,/,(),的计算后,使得计算得值为24,例如抽到1,2,2,5四张牌,那么
(1+5)*(2+2)=24;
这就是可以凑成24点的⼀种情况,作为⼀个经典题⽬,在leetcode上也有对应的题⽬进⾏练习
PS 看见知乎⼤佬有⼀种必24点的算法,但是要⽤到阶乘和次⽅式⼦为(a0+b0+c0+d0)! =24
⼀、总体思路
1.因为是简单暴⼒向的,所以我们的做法就是直接穷举出所有可能的情况,⾸先是考虑四个数a,b,c,d的排列情况
如b,a,c,d等等,通过排列组合可以得到 4*3*2*1 = 24 种情况
2.然后考虑a,b,c,d中的三个运算符的情况设⼀个⾃定义的运算符为,可以是+,-,*,/中的任意⼀个
则有 a b c$d 这个式⼦,同样,运算符的可能性有 3*4 = 12 种
3.最后考虑()的情况,我们规定,每次⼀对()只框住两个数,⽐如a+b+c+d =(((a+b)+c)+d) = ((r1+c)+d)=
(r2+d)=r3(其中r1=a+b,r2=r1+c,r3=r2+d)
()的情况其实就是运算优先级的问题,⽆论运算符是什么,都⼀定是先运算括号⾥的内容
所以我们可以穷举出情况
第⼀种r1=a b,r2=r1c,r3=r2$d;
第⼆种r1=b c,r2=a r1,r3=r2$d;
第三种r1=b c,r2=r1d,r3=a$r2;
第四种r1=c d,r2=b r1,r3=a$r2;
第五种r1=a b,r2=c d,r3=r1$r2;
仔细观察不难发现,我们控制了运算符和数字的绝对顺序从左到右的顺序严格是a b c$d,不论任何情况都不会改变abcd的顺序,是因为我们在上⾯已经排出来了所有的24种情况,所以我们这就可以严格控制abcd的顺序了
⼆、代码实现
1 #include <iostream>
2 #include <string>
3using namespace std;
4int mark_int[4] = { 1,2,3,4 };
5string mark_char = "+-*/";
6double cal(double a, int m, double b)
7 {
8switch (m)
9 {
10case1: return a + b;
11case2: return a - b;
12case3: return a * b;
13case4: return a / b;
14 }
15 }
16
17bool cal1(double a, double b, double c, double d, int m1, int m2, int m3)
18 {
19double r1;
20double r2;
21double r3;
22 r1 = cal(a, m1, b);
25if (r3 == 24)
26 {
27 cout << "(((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << ")" << endl;
28return1;
29 }
30return0;
31 }
32
33bool cal2(int a, int b, int c, int d, int m1, int m2, int m3)
34 {
35double r1;
36double r2;
37double r3;
38 r1 = cal(b, m1, c);
39 r2 = cal(a, m2, r1);
40 r3 = cal(r2, m3, d);
41if (r3 == 24)
42 {
43 cout << "((" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << c << "))" << mark_char[m3 - 1] << d << ")" << endl;
44return1;
45 }
46return0;
47 }
48
49bool cal3(int a, int b, int c, int d, int m1, int m2, int m3)
50 {
51double r1;
52double r2;
53double r3;
54 r1 = cal(b, m1, c);
55 r2 = cal(r1, m2, d);
56 r3 = cal(a, m3, r2);
57if (r3 == 24)
58 {
59 cout << "(" << a << mark_char[m1 - 1] << "((" << b << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << "))" << endl;
60return1;
61 }
62return0;
63 }
64
65bool cal4(int a, int b, int c, int d, int m1, int m2, int m3)
66 {
67double r1;
68double r2;
69double r3;
70 r1 = cal(c, m1, d);
71 r2 = cal(b, m2, r1);
72 r3 = cal(a, m3, r2);
73if (r3 == 24)
74 {
75 cout << "(" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << ")))" << endl;
76return1;
77 }
78return0;
79 }
80
81bool cal5(int a, int b, int c, int d, int m1, int m2, int m3)
82 {
83double r1;
84double r2;
85double r3;
86 r1 = cal(a, m1, b);
87 r2 = cal(c, m3, d);
88 r3 = cal(r1, m2, r2);
89if (r3 == 24)
90 {
91 cout << "((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << "))" << endl;
92return1;
93 }
94return0;
95 }
96
97
98bool all_cal(int a, int b, int c, int d)
99 {
100for (int i = 1; i <= 4; i++)
101for (int j = 1; j <= 4; j++)
102for (int k = 1; k <= 4; k++)
103 {
104if (cal1(a, b, c, d, i, j, k) == true || cal2(a, b, c, d, i, j, k) == true || cal3(a, b, c, d, i, j, k) == true || cal4(a, b, c, d, i, j, k) == true || cal5(a, b, c, d, i, j, k) == true) 105return1;
106 }
107return0;
108 }
110
111bool judge(int a, int b, int c, int d)
112 {
113int all[24][4] = {
114 {a,b,c,d},{a,b,d,c},{a,c,b,d},{a,c,d,b},{a,d,b,c},{a,d,c,b},
115 {b,a,c,d},{b,a,d,c},{b,c,a,d},{b,c,d,a},{b,d,a,c},{b,d,c,a},
116 {c,a,b,d},{c,a,d,b},{c,b,a,d},{c,b,d,a},{c,d,a,b},{c,d,b,a},
117 {d,a,b,d},{d,a,d,b},{d,b,a,c},{d,b,c,a},{d,c,a,b},{d,c,b,a},
118 };
119for (int i = 0; i < 24; i++)
120 {
121if (all_cal(all[i][0], all[i][1], all[i][2], all[i][3]))
122return1;
123 }
124return0;
125 }
126
127int main()
128 {
129int a, b, c, d;
130 cin >> a >> b >> c >> d;
131if (!judge(a, b, c, d))
132 cout << "凑不成24点" << endl;
133
134 }
三、代码解释
先做⼀个计算两个数的函数,⽤数组int mark_int[4] = {1,2,3,4}的四个数表⽰+ - * /,string mark_char是⽤来最后显⽰的
1int mark_int[4] = { 1,2,3,4 };
2string mark_char = "+-*/";
3double cal(double a, int m, double b)
4 {
5switch (m)//⽤switch来进⾏运算符的选择
6 {
7case1: return a + b;
8case2: return a - b;
9case3: return a * b;
10case4: return a / b;
11 }
12 }
我们在实现五种括号的函数,并且我们规定运算⼀定是 a m1 b m2 c m3 d(m1,m2,m3是三个运算符的代号),意思就是abcd的从左到右顺序不乱,m1m2m3从左到右的顺序也不会乱,⽐较粗暴的理解就是ab之间⼀定是m1,bc之间⼀定是m2,cd之间⼀定其实m3,然后如果成功返回运算的过程和true,否则返回false
1bool cal1(double a, double b, double c, double d, int m1, int m2, int m3)
2 {
3double r1;
4double r2;
5double r3;
6 r1 = cal(a, m1, b);
7 r2 = cal(r1, m2, c);
8 r3 = cal(r2, m3, d);
9if (r3 == 24)
10 {
11 cout << "(((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << ")" << endl;
12return1;
13 }
14return0;
15 }//第⼀种r1=a$b,r2=r1$c,r3=r2$d;
16
17bool cal2(int a, int b, int c, int d, int m1, int m2, int m3)
18 {
19double r1;
20double r2;
21double r3;
22 r1 = cal(b, m1, c);
23 r2 = cal(a, m2, r1);
24 r3 = cal(r2, m3, d);
25if (r3 == 24)
26 {
27 cout << "((" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << c << "))" << mark_char[m3 - 1] << d << ")" << endl;
28return1;
29 }
30return0;
31 }//第⼆种r1=b$c,r2=a$r1,r3=r2$d;
33bool cal3(int a, int b, int c, int d, int m1, int m2, int m3)
34 {
35double r1;
36double r2;
37double r3;
38 r1 = cal(b, m1, c);
39 r2 = cal(r1, m2, d);
40 r3 = cal(a, m3, r2);
41if (r3 == 24)
42 {
43 cout << "(" << a << mark_char[m1 - 1] << "((" << b << mark_char[m2 - 1] << c << ")" << mark_char[m3 - 1] << d << "))" << endl;
44return1;
45 }
46return0;
47 }//第三种r1=b$c,r2=r1$d,r3=a$r2;
48
49bool cal4(int a, int b, int c, int d, int m1, int m2, int m3)
50 {
51double r1;
52double r2;
53double r3;
54 r1 = cal(c, m1, d);
55 r2 = cal(b, m2, r1);
56 r3 = cal(a, m3, r2);
57if (r3 == 24)
58 {
59 cout << "(" << a << mark_char[m1 - 1] << "(" << b << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << ")))" << endl;
60return1;
61 }
62return0;
63 }//第四种r1=c$d,r2=b$r1,r3=a$r2;
64
65bool cal5(int a, int b, int c, int d, int m1, int m2, int m3)
66 {
67double r1;
68double r2;
69double r3;
70 r1 = cal(a, m1, b);
71 r2 = cal(c, m3, d);
72 r3 = cal(r1, m2, r2);
73if (r3 == 24)
74 {
75 cout << "((" << a << mark_char[m1 - 1] << b << ")" << mark_char[m2 - 1] << "(" << c << mark_char[m3 - 1] << d << "))" << endl;
76return1;
77 }
78return0;
79 }//第五种r1=a$b,r2=c$d,r3=r1$r2;
接下来是12种的符号的排列情况,如果有⼀种括号情况满⾜,我们就返回true,否则返回false
1bool all_cal(int a, int b, int c, int d)
2 {
3for (int i = 1; i <= 4; i++)
4for (int j = 1; j <= 4; j++)
5for (int k = 1; k <= 4; k++)
6 {
7if (cal1(a, b, c, d, i, j, k) == true || cal2(a, b, c, d, i, j, k) == true || cal3(a, b, c, d, i, j, k) == true || cal4(a, b, c, d, i, j, k) == true || cal5(a, b, c, d, i, j, k) == true) 8return1;
9 }
10return0;
11 }
最后是在总判断函数中写⼊24种的abcd排列情况
1bool judge(int a, int b, int c, int d)
2 {
3int all[24][4] = {
4 {a,b,c,d},{a,b,d,c},{a,c,b,d},{a,c,d,b},{a,d,b,c},{a,d,c,b},
5 {b,a,c,d},{b,a,d,c},{b,c,a,d},{b,c,d,a},{b,d,a,c},{b,d,c,a},
6 {c,a,b,d},{c,a,d,b},{c,b,a,d},{c,b,d,a},{c,d,a,b},{c,d,b,a},
7 {d,a,b,d},{d,a,d,b},{d,b,a,c},{d,b,c,a},{d,c,a,b},{d,c,b,a},
8 };
9for (int i = 0; i < 24; i++)
10 {
11if (all_cal(all[i][0], all[i][1], all[i][2], all[i][3]))
12return1;
13 }
14return0;
15 }
主函数调⽤judge就完成整个算法了✿✿ヽ(°▽°)ノ✿
1int main()
4 cin >> a >> b >> c >> d;
5if (!judge(a, b, c, d))
6 cout << "凑不成24点" << endl;
7
8 }
失败的话会显⽰“凑不成24点”
其实这个算法的话我写的可以说基本没有优化,就是枚举所有情况实现的,csdn上有⼤佬是有更好的思路的,这篇⽂章也是看了csdn的⼤佬的代码然后⾃⼰修修补补写出来的(我原来看的那篇有bug,⼤佬⾃⼰没发现好像。


就酱
睡觉!
Processing math: 0%。

相关文档
最新文档