自创题目:24点游戏

题目:这是源自生活中的一个经典小游戏。任意选出四张纸牌,上面有四个数字,(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;
}