首页 > 代码库 > 【算法29】速算24
【算法29】速算24
问题描述
题目来源:PAT ds 2-08
给定四个数字a, b, c, d,取值范围为[1, 13];添加合适的运算符 + , - , * , /, 和括号(, )使得表达式等于24,给出一种可能的表达式方案;如果不可能则返回-1。
例如:输入2, 3, 12, 12, 输出 ((3-2)*12) + 12.
输入5, 5, 5, 2, 输出-1.
问题分析
这个题目似乎没有好的算法,只能暴力搜索。
首先对于所有给个数字进行全排列,总过有$A_4^4 = 24$中排列方式;
然后对于每一种排列方式,需要添加三个运算符,每个运算符有加减乘除四种选择,总共有$4*4*4 = 64$中可能
最后对于得到的表达式进行加括号以改变优先级,总共只有5种加括号的方式:
- (A @ B)@(C@D);
- (A@(B@C))@D;
- ((A@B)@C)@D;
- A((B@C)@D);
- A@(B@(C@D));
因而所有可能的情况有 $24 * 64 * 5 = 7680$种选择。
定义子函数int calcluateBinaryExpression(int a, int b, char op) 来计算 a op b 的值;主函数首先do{}while(next_permutation)以获得所有的全排列过程,对于每个排列a, b, c, d,对于每一种加括号方式按照括号优先级计算表达式的值,判断是否等于24, 如果等于,直接return,否则,判断下一种加括号的方式。
注意:对于op == ‘/‘, a / b 时,需要保证 b != 0 && a % b == 0。如果不满足该条件,则直接进行下一轮循环。
程序源码
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 #include <functional> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <cassert> 9 using namespace std; 10 11 // given number a, b and operator ch, return eval(a ch b) 12 int calculateBinaryExpression(int a, int b, char ch) 13 { 14 switch(ch) 15 { 16 case ‘+‘: 17 return a + b; 18 break; 19 case ‘-‘: 20 return a - b; 21 break; 22 case ‘*‘: 23 return a * b; 24 break; 25 case ‘/‘: 26 assert(b != 0); 27 return a / b; 28 break; 29 default: 30 cerr << "WRONG OPERATOR !" << endl; 31 return -1; 32 break; 33 } 34 } 35 36 // Make 24 game 37 // BASIC IDEA: permutation all the possible cases: A(4, 4) = 24; 38 // Need 3 operators: 4 * 4 * 4 = 64; 39 // All five possible adding parenthese: 40 // (1) (A @ B) @ (C @ D) 41 // (2) (A @ (B @ C) ) @ D 42 // (3) ( (A @ B) @ C) @ D 43 // (4) A @ ( ( B @ C) @ D) 44 // (5) A @ ( B @ (C @ D) ) 45 // Total Possible cases: 24 * 64 * 5 = 7680, Brute Force 46 // Input: 4 numbers in [1, 13], 47 // use ‘+‘,‘-‘,‘*‘,‘/‘ and ‘(‘,‘)‘ to make 24 48 // Output: If it is possible to make 24, output the expression 49 // Else return -1; 50 // Notice: When calcalute x / y, need to assert (y != 0 && x % y == 0) 51 // If Not, continue 52 string make24(int num1, int num2, int num3, int num4) 53 { 54 vector<int> v(4, 0); 55 v[0] = num1; v[1] = num2; v[2] = num3; v[3] = num4; 56 sort(v.begin(), v.end()); 57 58 string ops("+-*/"); 59 60 do 61 { 62 // The first parenthesis 63 // (A @ B) @ (C @ D) 64 for (size_t i = 0; i < ops.size(); ++i) 65 { 66 // A @ B 67 char op1 = ops[i]; 68 if (op1 == ‘/‘ && (v[1] == 0 || v[0] % v[1] != 0)) continue; 69 int ans1 = calculateBinaryExpression(v[0], v[1], op1); 70 for (size_t j = 0; j < ops.size(); ++j) 71 { 72 // C @ D 73 char op2 = ops[j]; 74 if (op2 == ‘/‘ && (v[3] == 0 || v[2] % v[3] != 0)) continue; 75 int ans2 = calculateBinaryExpression(v[2], v[3], op2); 76 77 for (size_t k = 0; k < ops.size(); ++k) 78 { 79 // (A @ B) @ (C @ D) 80 char op3 = ops[k]; 81 if (op3 == ‘/‘ && (ans2 == 0 || ans1 % ans2 != 0)) continue; 82 int ans = calculateBinaryExpression(ans1, ans2, op3); 83 if (ans == 24) 84 { 85 string str; 86 str.push_back(‘(‘); 87 str += to_string((long long)(v[0])); 88 str.push_back(op1); 89 str += to_string((long long)(v[1])); 90 str.push_back(‘)‘); 91 str.push_back(op3); 92 str.push_back(‘(‘); 93 str += to_string((long long)(v[2])); 94 str.push_back(op2); 95 str += to_string((long long)(v[3])); 96 str.push_back(‘)‘); 97 return str; 98 } 99 }100 }101 102 }103 104 // The second parethesis105 // (A op2 (B op1 C)) op3 D106 for (size_t i = 0; i < ops.size(); ++i)107 {108 char op1 = ops[i];109 if (op1 == ‘/‘ && (v[2] == 0 || v[1] % v[2] != 0)) continue;110 int ans1 = calculateBinaryExpression(v[1], v[2], op1);111 for (size_t j = 0; j < ops.size(); ++j)112 {113 char op2 = ops[j];114 if (op2 == ‘/‘ && (ans1 == 0 || v[0] % ans1 != 0)) continue;115 int ans2 = calculateBinaryExpression(v[0], ans1, op2);116 for (size_t k = 0; k < ops.size(); ++k)117 {118 char op3 = ops[k];119 if (op3 == ‘/‘ && (v[3] == 0 || ans2 % v[3] != 0)) continue;120 int ans = calculateBinaryExpression(ans2, v[3], op3);121 if (ans == 24)122 {123 string str;124 str.push_back(‘(‘);125 str += to_string((long long)v[0]);126 str.push_back(op2);127 str.push_back(‘(‘);128 str += to_string((long long)v[1]);129 str.push_back(op1);130 str += to_string((long long)v[2]);131 str.push_back(‘)‘);132 str.push_back(‘)‘);133 str.push_back(op3);134 str += to_string((long long)v[3]);135 return str;136 }137 }138 }139 }140 141 // The third parentheses142 // ( ( A op1 B) op2 C) op3 D143 for (size_t i = 0; i < ops.size(); ++i)144 {145 char op1 = ops[i];146 if (op1 == ‘/‘ && (v[1] == 0 || v[0] % v[1] != 0)) continue;147 int ans1 = calculateBinaryExpression(v[0], v[1], op1);148 for (size_t j = 0; j < ops.size(); ++j)149 {150 char op2 = ops[j];151 if (op2 == ‘/‘ && (v[2] == 0 || ans1 % v[2] != 0)) continue;152 int ans2 = calculateBinaryExpression(ans1, v[2], op2);153 for (size_t k = 0; k < ops.size(); ++k)154 {155 char op3 = ops[k];156 if (op3 == ‘/‘ && (v[3] == 0 || ans2 % v[3] != 0)) continue;157 int ans = calculateBinaryExpression(ans2, v[3], op3);158 if (ans == 24)159 {160 string str("((");161 str += to_string((long long)v[0]);162 str.push_back(op1);163 str += to_string((long long)v[1]);164 str.push_back(‘)‘);165 str.push_back(op2);166 str += to_string((long long)v[2]);167 str.push_back(‘)‘);168 str.push_back(op3);169 str += to_string((long long)v[4]);170 return str;171 }172 }173 }174 }175 176 // The fourth parentheses177 // A op3 ( ( B op1 C ) op2 D)178 for (size_t i = 0; i < ops.size(); ++i)179 {180 char op1 = ops[i];181 if (op1 == ‘/‘ && (v[2] == 0 || v[1] % v[2] != 0)) continue;182 int ans1 = calculateBinaryExpression(v[1], v[2], op1);183 for (size_t j = 0; j < ops.size(); ++j)184 {185 char op2 = ops[j];186 if (op2 == ‘/‘ && (v[3] == 0 || ans1 % v[3] != 0)) continue;187 int ans2 = calculateBinaryExpression(ans1, v[3], op2);188 for (size_t k = 0; k < ops.size(); ++k)189 {190 char op3 = ops[k];191 if (op3 == ‘/‘ && (ans2 == 0 || v[0] % ans2 != 0)) continue;192 int ans = calculateBinaryExpression(v[0], ans2, op3);193 if (ans == 24)194 {195 string str;196 str += to_string((long long)v[0]);197 str.push_back(op3);198 str += "((";199 str += to_string((long long)v[1]);200 str.push_back(op1);201 str += to_string((long long)v[2]);202 str.push_back(‘)‘);203 str.push_back(op2);204 str += to_string((long long)v[3]);205 str.push_back(‘)‘);206 return str;207 }208 }209 }210 }211 212 // The fifth parenthese213 // A op3 ( B op2 ( C op1 D) );214 for (size_t i = 0; i < ops.size(); ++i)215 {216 char op1 = ops[i];217 if (op1 == ‘/‘ && (v[3] == 0 || v[2] % v[3] != 0)) continue;218 int ans1 = calculateBinaryExpression(v[2], v[3], op1);219 for (size_t j = 0; j < ops.size(); ++j)220 {221 char op2 = ops[j];222 if (op2 == ‘/‘ && (ans1 == 0 || v[1] % ans1 != 0)) continue;223 int ans2 = calculateBinaryExpression(v[1], ans1, op2);224 for (size_t k = 0; k < ops.size(); ++k)225 {226 char op3 = ops[k];227 if (op3 == ‘/‘ && (ans2 == 0 || v[0] % ans2 != 0)) continue;228 int ans = calculateBinaryExpression(v[0], ans2, op3);229 if (ans == 24)230 {231 string str;232 str += to_string((long long)v[0]);233 str.push_back(op3);234 str.push_back(‘(‘);235 str += to_string((long long)v[1]);236 str.push_back(op2);237 str.push_back(‘(‘);238 str += to_string((long long)v[2]);239 str.push_back(op1);240 str += to_string((long long)v[3]);241 str += "))";242 return str;243 }244 }245 }246 }247 248 } while(next_permutation(v.begin(), v.end()));249 250 return "-1";251 }252 253 int main()254 {255 int a, b, c, d;256 cin >> a >> b >> c >> d;257 string ans = make24(a, b, c, d);258 cout << ans << endl;259 return 0;260 }
参考文献
[1] 速算24算法思路
[2] 24 Game/Countdown/Number Game solver, but without parentheses in the answer
【算法29】速算24