前言

在这里插入图片描述


题解

2026国信杯具身智能创新大赛-编程技能赛的前身是睿抗 CAIP 编程赛。
今年比较特殊,直接略过了省赛,一场定国奖。
在这里插入图片描述
总计6题,满分130分,整体难度偏低,唯一的亮点是T4,一道有趣的构造题(最大二分匹配)。


GX-1 十万行代码

分值:10分
题型&知识点:签到

在这里插入图片描述

出题背景,挺有意思的

题意:
输出n遍 print(‘Hello World’)

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cout << "print('Hello World')\n";
    }
    return 0;
}

GX-2 一键"三连",这次一定

分值:15分
题型&知识点:模拟

题意:
b站视频的一键三连,给予用户id和动作(Like、Coin 或 Favorite)序列,然后按时间顺序输出完成一键三连的用户id列表。

#include <bits/stdc++.h>

using namespace std;

int main() {

    int n, m;
    cin >> n >> m;
    vector<int> arr(n+1);
  
    auto f = [](string &op) {
        if (op == "Like") return 0;
        else if (op == "Coin") return 1;
        else return 2;
    };

    int left = n;
    vector<int> res;
    for (int i = 0; i < m; i++) {
        int u; string op;
        cin >> u >> op;
        int fv = 1 << f(op);
        if (arr[u] != 7) {
            arr[u] |= fv;
            if (arr[u] == 7) {
                res.push_back(u);
                left--;
            }
        }
    }

    cout << "Complete: ";
    if (res.empty()) cout << "None\n";
    else {
        int z = res.size();
        for (int i = 0; i < z; i++) {
            cout << res[i] << " \n"[i == z - 1];
        }
    }
    cout<< "Incomplete: " << left << "\n";

    return 0;
}

GX-3 宿舍灯光秀

分值:20分
题型&知识点:模拟

题目:
给予一个n*m的二维0-1矩阵,支持按行,按列,按子矩阵翻转操作,求最终的1的个数。

因为数据范围和操作,O(nmq),0≤n,m≤100,q≤1000{O(nmq), 0\le n, m \le 100, q \le 1000}O(nmq),0n,m100,q1000, 即O(107){O(10^7)}O(107), 直接暴力枚举即可。

思考题:如果数据范围和操作数放大,可以如何求解?

如果只求最后的结果,可以用二维差分来加速,如果每个阶段都需要,感觉需要二维带lazy的线段树。

#include <bits/stdc++.h>

using namespace std;

int main() {

    int n, m, q;
    cin >> n >> m >> q;

    int now = 0;
    vector<vector<int>> g(n, vector<int>(m));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> g[i][j];
            if (g[i][j] == 1) now++;
        }
    }
    while (q-- > 0) {
        int op;
        cin >> op;
        if (op == 1) {
            int r; cin >> r;
            r--;
            for (int j = 0; j < m; j++) {
                g[r][j] = 1 - g[r][j];
                now += g[r][j] * 2 - 1;
            }
        } else if (op == 2) {
            int c; cin >> c;
            c--;
            for (int i = 0; i < n; i++) {
                g[i][c] = 1 - g[i][c];
                now += g[i][c] * 2 - 1;
            }
        } else {
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            x1--; y1--; x2--; y2--;

            for (int i = x1; i <= x2; i++) {
                for (int j = y1; j <= y2;j++) {
                    g[i][j] = 1 - g[i][j];
                    now += 2 * g[i][j] - 1;
                }
            }
        }
        cout << now << "\n";
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cout << g[i][j] << " \n"[j == m - 1];
        }
    }

    return 0;
}

GX-4 美丽平方数

分值:25分
题型&知识点:最大二分匹配,构造

题意:
给予2个1~n的排列{aaa}, {bbb}, 需要构造一个排列,使得对于任意的i, 1≤i≤n1\le i \le n1in, 满足ai+bi是平方数{a_i + b_i是平方数}ai+bi是平方数

在这里插入图片描述

思路:
抽象为一个二分图,分别为{aaa}, {bbb}, 如果满足 ai+bj{a_i+b_j}ai+bj 为平方数,则在aia_iaibjb_jbj建边,因为要一一匹配,所以就是一道很巧妙且裸的最大二分匹配板子题。

采用匈牙利算法,寻找增广路径,时间复杂度为O(V∗E)O(V*E)O(VE).

#include <bits/stdc++.h>

using namespace std;

int main() {

    int N = 100;
    set<int> st;
    for (int i = 1; i <= N; i++) {
        st.insert(i * i);
    }

    int t;
    cin >> t;
    while (t-- > 0) {
        int n;
        cin >> n;

        vector<vector<int>> g(n + 1);

        // 构建二分图
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (st.find(i + j) != st.end()) {
                    g[i].push_back(j);
                }
            }
        }

        // 
        vector<int> match(n + 1, -1);
        function<bool(int u, vector<int>& seen)> dfs;
        dfs = [&](int u, vector<int> &seen) -> bool {
            for (int v: g[u]) {
                if (seen[v]) continue;
                seen[v] = 1;
                if (match[v] == -1 || dfs(match[v], seen)) {
                    match[v] = u;
                    return true;
                }
            }
            return false;
        };

        int cnt = 0;
        for (int i = 1; i <= n; i++) {
            vector<int> seen(n + 1);
            if (dfs(i, seen)) {
                cnt++;
            }
        }

        if (cnt < n) {
            cout << "no\n";
        } else {
            for (int i = 1; i <= n; i++) {
                cout << match[i] << " \n"[i == n];
            }
        }
    }

    return 0;
}

GX-5 不稳定因素

分值:30分
题型和知识点:并查集

关系的传递性,往往采用并查集,来维护集合关系。

#include <bits/stdc++.h>

using namespace std;

struct Dsu {
    int n, m;
    vector<int> arr;

    Dsu(int n)
            : n(n), m(n), arr(n, -1) {}
    int find(int u) {
        if (arr[u] == -1) return u;
        return arr[u] = find(arr[u]);
    }

    void merge(int u, int v) {
        int a= find(u), b = find(v);
        if (a != b) {
            arr[a] = b;
            m--;
        }
    }

    int gs() { return m; }
};

int main() {

    int n, m;
    cin >> n >> m;
    vector<int> ps(n);
    for (int &x: ps) cin >> x;

    vector<vector<array<int, 2>>> g(n);
    Dsu dsu(n);
    for (int i = 0; i < m; i++) {
        int u, v, r;
        cin >> u >> v >> r;
        u--; v--;
        if (r != 0) {
            dsu.merge(u, v);
            g[u].push_back({v, r});
            g[v].push_back({u, r});
        }
    }

    vector<int64_t> grp(n);
    for (int i = 0; i < n; i++) {
        for (auto &e: g[i]) {
            int p = dsu.find(i), r = e[1];
            grp[p] += r / (1 + abs(ps[i] - ps[e[0]]));
        }
    }

    int sum = 0;
    cout << dsu.gs() << "\n";
    vector<int> res1;
    for (int i = 0; i < n; i++) {
        if (dsu.find(i) == i) {
            res1.push_back(grp[i] / 2);
            sum += grp[i] / 2;
        }
    }
    sort(res1.begin(), res1.end());
    int rn1 = res1.size();
    for (int i = 0; i < rn1; i++) {
        cout << res1[i] << " \n"[i == rn1 - 1];
    }

    int ans = 0;
    vector<int> clist;

    for (int i = 0; i < n; i++) {
        int delta = 0;
        for (auto &e: g[i]) {
            int v1 = e[1] / (1 + abs(ps[i] - ps[e[0]]));
            int v2 = e[1] / (1 + abs(ps[e[0]]));

            delta += v2 - v1;
        }

        if (delta > ans) {
            ans = delta;
            clist = {i};
        } else if (delta == ans) {
            clist.push_back(i);
        }
    }

    if (clist.empty()) cout << "NONE\n";
    else {
        int rn2 = clist.size();
        for (int i = 0; i < rn2; i++) {
            cout << (clist[i] + 1) << " \n"[i == rn2 - 1];
        }
    }

    cout << max(sum, sum + ans) << "\n";

    return 0;
}

GX-6 赶上末班车

分值:30分
题型&知识点:dijkstra最短路
在这里插入图片描述

注意单向边,边权的动态计算,非常的板。

#include <bits/stdc++.h>

using namespace std;

struct E {
    int v, s, p, d, t;
    E() {}
    E(int v, int s, int p, int d, int t)
        : v(v), s(s), p(p), d(d), t(t) {}
};

struct X {
    int u;
    int w;
    X() {}
    X(int u, int w)
        : u(u), w(w) {}
};

int main() {

    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    
    int n, m, S, T, ts;
    cin >> n >> m >> S >> T >> ts;

    S--; T--;
    vector<vector<E>> g(n);
    for (int i = 0; i < m; i++) {
        int u, v, s, p, d, t;
        cin >> u >> v >> s >> p >> d >> t;
        u--; v--;
        g[u].push_back(E(v, s, p, d, t));
    }

    auto comp = [](const X&a, const X&b) {
        return a.w > b.w;
    };
    priority_queue<X, vector<X>, decltype(comp)> pq(comp);

    int inf = (int)2e9;
    vector<int> dp(n, inf);

    dp[S] = ts;
    pq.push(X(S, ts));

    while (!pq.empty()) {
        X x = pq.top(); pq.pop();
        if (x.w > dp[x.u]) continue;

        for (auto &e: g[x.u]) {
            int y = (max(x.w, e.s) - e.s + e.p - 1)  / e.p;
            if (e.s + y * e.p <= e.d) {
                if (dp[e.v] > e.s + y * e.p + e.t) {
                    dp[e.v] = e.s + y * e.p + e.t;
                    pq.push(X(e.v, dp[e.v]));
                }
            }
        }
    }

    if (dp[T] == inf) {
        cout << "Go Taxi\n";
    } else {
        cout << dp[T] << "\n";
    }

    return 0;
}

写在最后

在这里插入图片描述

Logo

电影级数字人,免显卡端渲染SDK,十行代码即可调用,工业级demo免费开源下载!

更多推荐