24点问题
CSDN编程挑战里的题目
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则正确.可惜提交了三次才正确,没有获奖的机会了.
我的程序还可以输出其运算的表达式.
1 #include <stdio.h> 2 #include <iostream> 3 #include <string> 4 5 #include <cmath> 6 #include <cfloat> 7 #include <cstring> 8 #include <cstdio> 9 10 // 4张牌的排列组合 11 const int g_fourlist[24][4] = 12 { 13 {0,1,2,3}, 14 {0,1,3,2}, 15 {0,2,1,3}, 16 {0,2,3,1}, 17 {0,3,2,1}, 18 {0,3,1,2}, 19 20 {1,2,3,0}, 21 {1,2,0,3}, 22 {1,3,2,0}, 23 {1,3,0,2}, 24 {1,0,2,3}, 25 {1,0,3,2}, 26 27 {2,1,3,0}, 28 {2,1,0,3}, 29 {2,3,1,0}, 30 {2,3,0,1}, 31 {2,0,1,3}, 32 {2,0,3,1}, 33 34 {3,1,2,0}, 35 {3,1,0,2}, 36 {3,2,1,0}, 37 {3,2,0,1}, 38 {3,0,1,2}, 39 {3,0,2,1}, 40 }; 41 42 void _buildExpress(int a, int b, int c, int d, int n, int i, int j, int k, char* szExpress) 43 { 44 char szN[2] = {0}; 45 char szI[2] = {0}; 46 char szJ[2] = {0}; 47 char szK[2] = {0}; 48 49 if (n&1) 50 { 51 szN[0] = '-'; 52 } 53 54 switch (i) 55 { 56 case 0: 57 szI[0] = '+'; 58 break; 59 case 1: 60 szI[0] = '-'; 61 break; 62 case 2: 63 szI[0] = '*'; 64 break; 65 case 3: 66 szI[0] = '/'; 67 break; 68 } 69 70 switch (j) 71 { 72 case 0: 73 szJ[0] = '+'; 74 break; 75 case 1: 76 szJ[0] = '-'; 77 break; 78 case 2: 79 szJ[0] = '*'; 80 break; 81 case 3: 82 szJ[0] = '/'; 83 break; 84 } 85 86 switch (k) 87 { 88 case 0: 89 szK[0] = '+'; 90 break; 91 case 1: 92 szK[0] = '-'; 93 break; 94 case 2: 95 szK[0] = '*'; 96 break; 97 case 3: 98 szK[0] = '/'; 99 break; 100 } 101 102 if (n&2) 103 { 104 sprintf(szExpress, "%s%d %s %d %s (%d %s %d) == 24", szN, a, szI, b, szJ, c, szK, d); 105 } 106 else 107 { 108 sprintf(szExpress, "%s%d %s %d %s %d %s %d == 24", szN, a, szI, b, szJ, c, szK, d); 109 } 110 } 111 112 /* 113 表达式的组合有以下四类: 114 a?b?c?d 115 (-a)?b?c?d) 116 (a?b) ? (c?d) 117 ((-a)?b) ? (c?d)) 118 表达式从左向右计算, 119 +,-,*,/无优先级顺序 120 121 6/(1-(3/4)) 122 */ 123 124 bool _can24(int a, int b, int c, int d, char* szExpress) 125 { 126 float valueA; 127 float valueAB; 128 float valueABC; 129 float valueCD; 130 float valueABCD; 131 132 for (int n = 0; n < 4; n++) 133 { 134 valueA = (n&1) ? -(float)a : (float)a; 135 136 for (int i = 0; i < 4; i++) 137 { 138 switch (i) 139 { 140 case 0: 141 valueAB = valueA+b; 142 break; 143 case 1: 144 valueAB = valueA-b; 145 break; 146 case 2: 147 valueAB = valueA*b; 148 break; 149 case 3: 150 valueAB = valueA/b; 151 break; 152 } 153 154 if (n&2) 155 { 156 // (a?b) ? (c?d) 157 for (int k = 0; k < 4; k++) 158 { 159 switch (k) 160 { 161 case 0: 162 valueCD = (float)c+d; 163 break; 164 case 1: 165 valueCD = (float)c-d; 166 break; 167 case 2: 168 valueCD = (float)c*d; 169 break; 170 case 3: 171 valueCD = (float)c/d; 172 break; 173 } 174 175 for (int j = 0; j < 4; j++) 176 { 177 switch (j) 178 { 179 case 0: 180 valueABCD = valueAB+valueCD; 181 break; 182 case 1: 183 valueABCD = valueAB-valueCD; 184 break; 185 case 2: 186 valueABCD = valueAB*valueCD; 187 break; 188 case 3: 189 valueABCD = valueAB/valueCD; 190 break; 191 } 192 193 if (fabs(valueABCD - 24) < FLT_EPSILON) 194 { 195 if (szExpress) 196 { 197 _buildExpress(a, b, c, d, n, i, j, k, szExpress); 198 } 199 return true; 200 } 201 } 202 } 203 } 204 else 205 { 206 for (int j = 0; j < 4; j++) 207 { 208 switch (j) 209 { 210 case 0: 211 valueABC = valueAB+c; 212 break; 213 case 1: 214 valueABC = valueAB-c; 215 break; 216 case 2: 217 valueABC = valueAB*c; 218 break; 219 case 3: 220 valueABC = valueAB/c; 221 break; 222 } 223 224 for (int k = 0; k < 4; k++) 225 { 226 switch (k) 227 { 228 case 0: 229 valueABCD = valueABC+d; 230 break; 231 case 1: 232 valueABCD = valueABC-d; 233 break; 234 case 2: 235 valueABCD = valueABC*d; 236 break; 237 case 3: 238 valueABCD = valueABC/d; 239 break; 240 } 241 242 if (fabs(valueABCD - 24) < FLT_EPSILON) 243 { 244 if (szExpress) 245 { 246 _buildExpress(a, b, c, d, n, i, j, k, szExpress); 247 } 248 return true; 249 } 250 else if (fabs(valueABCD - 1.0f/24) < FLT_EPSILON) 251 { 252 // 1/24也可以 253 if (szExpress) 254 { 255 _buildExpress(a, b, c, d, n, i, j, k, szExpress); 256 } 257 return true; 258 } 259 } 260 } 261 } 262 } 263 } 264 265 return false; 266 } 267 268 bool Can24(const int four[4], char* szExpress) 269 { 270 for (int i = 0; i < 24; i++) 271 { 272 if (_can24(four[g_fourlist[i][0]], 273 four[g_fourlist[i][1]], 274 four[g_fourlist[i][2]], 275 four[g_fourlist[i][3]], 276 szExpress)) 277 { 278 return true; 279 } 280 } 281 282 return false; 283 }