B4534

[信息与未来 2026] 桌面游戏

数字顺序固定,真正要搜索的是“当前数字放哪个空格”。

一、先回答问题

结论

用极小化极大:Dr. X 让最终 `x-y` 尽量大,Dr. Y 让最终 `x-y` 尽量小。

课堂安排

先抓住模型,再用一个小样例手推,最后把判断写成稳定的 C++14 代码。

二、核心观察

搜索层

第 t 层放剩余数字中的第 t 个。

决策

偶数层取 max,奇数层取 min。

三、互动演示

XY算分

四、自己选答案

问题 1:这题最关键的状态是什么?

五、手推结果

函数作用
`dfs(t)`从第 t 个剩余数字开始,双方最优后的最终分差
`score()`计算三行乘积和减三列乘积和
`memo`记忆化相同局面

六、C++14 参考代码

#include <bits/stdc++.h>
using namespace std;

int a[9];
vector<int> nums;
unordered_map<string, int> memo;

int score() {
    int x = 0, y = 0;
    for (int i = 0; i < 3; i++) {
        x += a[i * 3] * a[i * 3 + 1] * a[i * 3 + 2];
        y += a[i] * a[i + 3] * a[i + 6];
    }
    return x - y;
}

string key(int t) {
    string s;
    s.reserve(10);
    s.push_back(char('0' + t));
    for (int i = 0; i < 9; i++) s.push_back(char('0' + a[i]));
    return s;
}

int dfs(int t) {
    if (t == (int)nums.size()) return score();
    string k = key(t);
    if (memo.count(k)) return memo[k];

    int cur = nums[t];
    if (t % 2 == 0) { // Dr. X: maximize x-y
        int res = -1e9;
        for (int i = 0; i < 9; i++) {
            if (a[i] == 0) {
                a[i] = cur;
                res = max(res, dfs(t + 1));
                a[i] = 0;
            }
        }
        return memo[k] = res;
    } else {          // Dr. Y: minimize x-y
        int res = 1e9;
        for (int i = 0; i < 9; i++) {
            if (a[i] == 0) {
                a[i] = cur;
                res = min(res, dfs(t + 1));
                a[i] = 0;
            }
        }
        return memo[k] = res;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    while (T--) {
        bool used[10] = {};
        for (int i = 0; i < 9; i++) {
            cin >> a[i];
            if (a[i]) used[a[i]] = true;
        }
        nums.clear();
        for (int x = 1; x <= 9; x++) {
            if (!used[x]) nums.push_back(x);
        }
        memo.clear();
        int diff = dfs(0);
        if (diff > 0) cout << "first\n";
        else if (diff < 0) cout << "second\n";
        else cout << "tie\n";
    }
    return 0;
}
读代码重点

先看状态变量,再看核心判断,最后检查边界和输出格式。