2026国信杯具身智能创新大赛-编程技能赛--本科组国赛解题报告 | 珂学家
前言

题解
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),0≤n,m≤100,q≤1000, 即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 n1≤i≤n, 满足ai+bi是平方数{a_i + b_i是平方数}ai+bi是平方数

思路:
抽象为一个二分图,分别为{aaa}, {bbb}, 如果满足 ai+bj{a_i+b_j}ai+bj 为平方数,则在aia_iai和bjb_jbj建边,因为要一一匹配,所以就是一道很巧妙且裸的最大二分匹配板子题。
采用匈牙利算法,寻找增广路径,时间复杂度为O(V∗E)O(V*E)O(V∗E).
#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;
}
写在最后

更多推荐




所有评论(0)