如果你是移动端,我推荐点击这个看链接看推送版的
推送版的链接
题目描述:
24点是一个有趣的扑克牌游戏。发4张牌,然后计算是否能够算出24点来。(不考虑有括号的算式,输出计算式将从左到有进行计算)
如果可以,输出算数表达式;
如果不可以,输出NONE
如果表达式中,有错误输入,输出“ERROR”
输入实例:
2
AAAA
Q3J8
输出实例:
NONE
Q-J*3*8
代码解析:
下面解析,将以对其中一组数据(4个字符)为例
- main函数中读入字符串
- 先选择第一个数
- 开始深搜,一直到搜了四个数之后,判断是否为24,是就将更新答案,并返回True
- 进行选择,每一次深搜,都是选择一个运算符和一个数字(字符)。用tempAns来记录表达式。
- 注意要对深搜部分进行恢复,避免影响下一次深搜。同时用visited记录访问过的点,避免重复使用,并进入死循环。(答案错了就检查是不是没有深搜恢复好;出现死循环,很有可能是因为没有标记访问过的点)
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
char cards[4];
bool visited[4];
char cal[] = {'+', '-', '*', '/'};
string ans, tempAns;
double tempNum;
int charToNum(char c) {
if (c <= '9' && c>= '0') {
return c - '0';
} else if (c == 'J') {
return 11;
} else if (c == 'Q') {
return 12;
} else if (c == 'K') {
return 13;
} else if (c == 'A') {
return 1;
}
return -1;
}
bool DFS(int now) { // now From 1
if(now == 4) {
if (abs(tempNum - 24) < 1e-6) {
ans = tempAns;
return true;
}
return false;
}
// choose a cal
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
if (!visited[j]) {
if (i == 0) {
tempNum += charToNum(cards[j]);
visited[j] = true;
tempAns.push_back(cal[i]);
tempAns.push_back(cards[j]);
} else if (i == 1) {
tempNum -= charToNum(cards[j]);
visited[j] = true;
tempAns.push_back(cal[i]);
tempAns.push_back(cards[j]);
} else if (i == 2) {
tempNum *= charToNum(cards[j]);
visited[j] = true;
tempAns.push_back(cal[i]);
tempAns.push_back(cards[j]);
} else if (i == 3) {
tempNum /= charToNum(cards[j]);
visited[j] = true;
tempAns.push_back(cal[i]);
tempAns.push_back(cards[j]);
}
if(DFS(now + 1)) {
return true;
}
if (i == 0) {
tempNum -= charToNum(cards[j]);
visited[j] = false;
tempAns = tempAns.substr(0, tempAns.length() - 2);
} else if (i == 1) {
tempNum += charToNum(cards[j]);
visited[j] = false;
tempAns = tempAns.substr(0, tempAns.length() - 2);
} else if (i == 2) {
tempNum /= charToNum(cards[j]);
visited[j] = false;
tempAns = tempAns.substr(0, tempAns.length() - 2);
} else if (i == 3) {
tempNum *= charToNum(cards[j]);
visited[j] = false;
tempAns = tempAns.substr(0, tempAns.length() - 2);
}
}
}
}
return false;
}
int main(){
int time, fa;
cin >> time;
while(time--) {
char c;
fa = true;
for (int i = 0; i < 4; ++i){
cin >> c;
if (c <= '9' && c>= '0' || c == 'J' || c == 'Q' || c == 'K' || c == 'A') {
cards[i] = c;
} else {
fa = false;
}
}
if (!fa) {
cout << "Error!\n"; continue;
}
memset(visited, false, sizeof(visited));
bool ok = false;
for (int i = 0; i < 4; ++i) {
tempAns.clear();
visited[i] = true;
tempAns.push_back(cards[i]);
tempNum = charToNum(cards[i]);
if (DFS(1)){
cout<< ans<< endl;
ok = true;
break;
}
visited[i] = false;
}
if (!ok) {
cout << "NONE\n";
}
}
}
类似需求的一个改进版本
- 但任然不完善,没办法解决 1 5 5 5 这个数学式子的24点问题。
#include <iostream>
#include <stack>
#include <string>
#include <cmath>
using namespace std;
double arr[4];
struct pi{
int v, op;
/*
l: temp value
r: each number in arr
op:
0: l + r
1: l - r
2: r - l
3: l / r
4: r / l
5: l * r
*/
pi(int v_ = 0, int op_ = 0) {
v = v_;
op = op_;
}
};
stack< pi > tmp_path;
bool visited[4];
bool DFS(int temp, int time) {
if (time == 4) { return abs(temp - 24) < 1e-6; }
double value;
for (int i = 1; i < 4; ++i) {
if (visited[i]) continue;
else visited[i] = true;
value = arr[i];
// op:0, temp + value
tmp_path.push(pi(value, 0));
if (DFS(temp + value, time + 1))
return true;
tmp_path.pop();
// op:1, temp - value
tmp_path.push(pi(value, 1));
if (DFS(temp - value, time + 1))
return true;
tmp_path.pop();
// op:2, value - temp
tmp_path.push(pi(value, 2));
if (DFS(value - temp, time + 1))
return true;
tmp_path.pop();
// op:3, temp / value
tmp_path.push(pi(value, 3));
if (DFS(temp / value, time + 1))
return true;
tmp_path.pop();
// op:4, value - temp
tmp_path.push(pi(value, 4));
if (DFS(value / temp, time + 1))
return true;
tmp_path.pop();
// op:5, temp * value
tmp_path.push(pi(value, 5));
if (DFS(temp * value, time + 1))
return true;
tmp_path.pop();
visited[i] = false;
}
return false;
}
string returnCalStr(int time) {
string s;
string op_str;
if (time == 3) {
s = to_string(int(arr[0]));
return s;
}
else {
pi t_pi = tmp_path.top();
s = to_string(int(t_pi.v));
tmp_path.pop();
string tmp = returnCalStr(time+1);
if (t_pi.op == 0) {
op_str = string("+");
}
else if (t_pi.op == 1 || t_pi.op == 2) {
op_str = string("-");
}
else if (t_pi.op == 3 || t_pi.op == 4) {
op_str = string("/");
}
else op_str = string("*");
if (t_pi.op == 2 || t_pi.op == 4) {
return string("(") + s + op_str + tmp + string(")");
}
else {
return string("(") + tmp + op_str + s + string(")");
}
}
}
void print_path() {
cout << returnCalStr(0) << endl;
}
int main() {
int time;
cin >> time;
while (time--) {
for (int i = 0; i < 4; ++i) {
cin >> arr[i];
}
for (int i = 0; i < 4; ++i) visited[i] = false;
visited[0] = true;
if (DFS(arr[0], 1)) {
print_path();
}
else {
cout << "None\n";
}
}
system("pause");
}