题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1427
思路分析:
题目要求判断是否存在一种运算组合使得4个数的计算结果为24,因为搜索的层次为3层,不需要选择出最短的路径,采用dfs更有效;
拓展状态时,从当前状态拥有的数中选取两个进行某种运算(因为两个数之间存在大小关系,所以对于除法与减法来说,运算顺序一定,
大的数为被减数或被除数;加法与乘法具有交换律,相对顺序没有影响),如果可以进行运算且运算结果满足题目要求,则该状态可以
拓展,如此拓展状态,直到检测到存在一种可能的运算顺序使运算结果为24。
代码如下:
#include <iostream> #include <cmath> using namespace std; struct Cards { int num[4]; int len; }; int Max(int lhs, int rhs) { return lhs > rhs ? lhs : rhs; } int Min(int lhs, int rhs) { return lhs > rhs ? rhs : lhs; } double Calculate(int i, int t_lhs, int t_rhs, bool &ok) { int lhs, rhs; lhs = Max(t_lhs, t_rhs); rhs = Min(t_lhs, t_rhs); if (i == 0) return lhs + rhs; if (i == 1) return lhs - rhs; if (i == 2) return lhs * rhs; if (i == 3) { if (rhs != 0 && lhs >= rhs && lhs % rhs == 0) return lhs / rhs; else { ok = false; return 0; } } } void dfs(Cards start, bool &find_ans) { if (start.len == 1) { if (start.num[0] == 24) find_ans = true; return; } else { int len = start.len; for (int i = 0; i < len; ++i) { for (int j = i + 1; j < len; ++j) { int count = 0; int lhs = start.num[i]; int rhs = start.num[j]; Cards next; for (int k = 0; k < len; ++k) { if (k != i && k != j) next.num[count++] = start.num[k]; } next.len = count + 1; for (int k = 0; k < 4; ++k) { bool ok = true; double result = Calculate(k, lhs, rhs, ok); if (find_ans) return; if (!ok || result != (int)result) continue; next.num[count] = result; dfs(next, find_ans); } } } } } int StrToInt(char *s) { int result = 0; if (s[0] == 'A') result = 1; else if (s[0] == 'J') result = 11; else if (s[0] == 'Q') result = 12; else if (s[0] == 'K') result = 13; else if (s[0] == '1' && s[1] == '0') result = 10; else result = s[0] - '0'; return result; } int main() { Cards start; bool find_ans; char temp[5]; while (scanf("%s", &temp) != EOF) { find_ans = false; start.len = 4; start.num[0] = StrToInt(temp); for (int i = 1; i < 4; ++i) { scanf("%s", &temp); start.num[i] = StrToInt(temp); } dfs(start, find_ans); if (find_ans) cout << "Yes "; else cout << "No "; } return 0; }