题目:这是源自生活中的一个经典小游戏。任意选出四张纸牌,上面有四个数字,(J对应11 Q对应12 K对应13)进行加减乘除运算,最终得到24。
要求:每个纸牌上的数字必须且只能使用一次,可以进行分数运算。不能进行平方、幂运算。
cpp
#include <bits/stdc++.h>
using namespace std;
// 分数结构体
struct Frac {
int num, den;
Frac(int n = 0, int d = 1) {
if (d < 0) { n = -n; d = -d; }
int g = __gcd(abs(n), d);
num = n / g;
den = d / g;
}
};
// 分数四则运算
Frac add(Frac a, Frac b) { return Frac(a.num*b.den + b.num*a.den, a.den*b.den); }
Frac sub(Frac a, Frac b) { return Frac(a.num*b.den - b.num*a.den, a.den*b.den); }
Frac mul(Frac a, Frac b) { return Frac(a.num*b.num, a.den*b.den); }
Frac divv(Frac a, Frac b) {
if (b.num == 0) return Frac(0,1);
return Frac(a.num*b.den, a.den*b.num);
}
int n = 4;
Frac a[4];
string expr[4]; // 存储每个数字对应的表达式
bool used[4];
bool found = false;
void dfs(int cnt) {
if (found) return;
if (cnt == 1) {
for (int i = 0; i < 4; i++) {
if (!used[i]) {
if (a[i].num == 24 && a[i].den == 1) {
found = true;
cout << "可以计算出 24!表达式为:" << endl;
cout << expr[i] << " = 24" << endl;
}
return;
}
}
}
for (int i = 0; i < 4; i++) {
if (used[i]) continue;
for (int j = i+1; j < 4; j++) {
if (used[j]) continue;
Frac ti = a[i], tj = a[j];
string si = expr[i], sj = expr[j];
used[j] = true;
// 1. a + b
a[i] = add(ti, tj);
expr[i] = "(" + si + "+" + sj + ")";
dfs(cnt-1);
// 2. a - b
a[i] = sub(ti, tj);
expr[i] = "(" + si + "-" + sj + ")";
dfs(cnt-1);
// 3. b - a
a[i] = sub(tj, ti);
expr[i] = "(" + sj + "-" + si + ")";
dfs(cnt-1);
// 4. a * b
a[i] = mul(ti, tj);
expr[i] = "(" + si + "*" + sj + ")";
dfs(cnt-1);
// 5. a / b
if (tj.num != 0) {
a[i] = divv(ti, tj);
expr[i] = "(" + si + "/" + sj + ")";
dfs(cnt-1);
}
// 6. b / a
if (ti.num != 0) {
a[i] = divv(tj, ti);
expr[i] = "(" + sj + "/" + si + ")";
dfs(cnt-1);
}
// 恢复现场
a[i] = ti;
expr[i] = si;
a[j] = tj;
expr[j] = sj;
used[j] = false;
}
}
}
int main() {
cout << "请输入四个 1-30 之间的自然数:";
for (int i = 0; i < 4; i++) {
cin >> a[i].num;
a[i].den = 1;
expr[i] = to_string(a[i].num);
}
found = false;
memset(used, false, sizeof(used));
dfs(4);
if (!found)
cout << "无法计算出 24。" << endl;
return 0;
}