2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛)
2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛)
前言
补题只补了前四道,第五题打个暴力都有 \(24\) 分,我这死活只有 \(22\) 分 \(QAQ\)
RC-u1 大家一起查作弊
思路
按题意模拟。
不过很奇怪赛时用 getline 老是读入不了,还好换成 cin 直接读也问题不大。
代码
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); auto check0 = [](char c)->bool{ bool res = 0; if (c >= '0' && c <= '9') res = 1; if (c >= 'a' && c <= 'z') res = 1; if (c >= 'A' && c <= 'Z') res = 1; return res; }; auto check1 = [](string s)->int{ int res = 0; for (int i = 0; i < s.size(); i ++) { if (s[i] >= '0' && s[i] <= '9') res ++; } return res; }; auto check2 = [](string s)->int{ int res = 0; for (int i = 0; i < s.size(); i ++) { if (s[i] >= 'a' && s[i] <= 'z') res ++; } return res; }; auto check3 = [](string s)->int{ int res = 0; for (int i = 0; i < s.size(); i ++) { if (s[i] >= 'A' && s[i] <= 'Z') res ++; } return res; }; vector<string> a; string s; while (cin >> s) { for (int i = 0; i < s.size(); i ++) { if (check0(s[i])) { int j = i + 1; while (j < s.size() && check0(s[j])) { j ++; } a.emplace_back(s.substr(i, j - i)); i = j; } } } int ans1 = 0, ans2 = 0; for (auto s : a) { ans2 += s.size(); int x = check1(s), y = check2(s), z = check3(s); if (x && y && z) ans1 += 5; else if (x && (y || z)) ans1 += 3; else if (y && z) ans1 += 1; } cout << ans1 << '\n' << ans2 << ' ' << a.size() << '\n'; return 0; }
RC-u2 谁进线下了?II
思路
按题意模拟,注意不要输出未参赛的队伍分数。
代码
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); auto get = [](int x)->int{ if (x == 1) return 25; if (x == 2) return 21; if (x == 3) return 18; return 20 - x; }; int n; cin >> n; vector<array<int, 2>> a(31); for (int i = 1; i <= 30; i ++) { a[i][1] = i; } set<int> ok; while (n--) { for (int i = 1; i <= 20; i ++) { int c, p; cin >> c >> p; a[c][0] += get(p); ok.insert(c); } } sort(a.begin() + 1, a.end(), [](auto x, auto y) { if (x[0] == y[0]) return x[1] < y[1]; return x[0] > y[0]; }); for (int i = 1; i <= 30; i ++) { if (ok.count(a[i][1])) { cout << a[i][1] << ' ' << a[i][0] << '\n'; } } return 0; }
RC-u3 势均力敌
思路
赛后听佬们说有规律,不过我是蠢比找不出规律,只好写暴力了 \(\dots\)
考虑到 \(4!=24\),直接暴力搜索有 \(2^{24}\) 会超时,那就双向搜索好了,要找两个集合,使其平方和相等, 枚举一半 \(2^{12}\) 找到两个集合各一半的和假设为 \([a,b]\),再枚举另一半找到的和假设为 \([c,d]\),那么有 \(a+c=b+d\),即 \(a-b=d-c\),所以我们只要存下差值即可,然后还要存下两个集合中选的数有没有一半,这里我是直接判断状态中 \(1\) 的个数有没有一半,找到了就直接输出。
代码
#include <bits/stdc++.h> using i64 = long long; using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; vector<int> a(n + 1); for (int i = 1; i <= n; i ++) cin >> a[i]; vector<int> num; int vis[5] {}; auto dfs = [&](auto & self, int x, int res)->void{ if (x == n) { num.emplace_back(res); return ; } for (int i = 1; i <= n; i ++) { if (!vis[i]) { vis[i] = 1; self(self, x + 1, res * 10 + a[i]); vis[i] = 0; } } }; dfs(dfs, 0, 0); int y = 1; for (int i = 1; i <= n; i ++) y *= i; y /= 2; auto print = [&](int a, int b)->void{ for (int i = 0; i < y; i ++) { if (a >> i & 1) { cout << num[i] << '\n'; } } for (int i = 0; i < y; i ++) { if (b >> i & 1) { cout << num[i + y] << '\n'; } } }; map<i64, vector<int>> mp; for (int i = 1; i < (1 << y); i ++) { i64 f = 0, res1 = 0, res0 = 0; for (int j = 0; j < y; j ++) { if (i >> j & 1) { res1 += num[j] * num[j]; } else { res0 += num[j] * num[j]; } } mp[res1 - res0].push_back(i); } for (int i = 1; i < (1 << y); i ++) { i64 f = 0, res1 = 0, res0 = 0; for (int j = 0; j < y; j ++) { if (i >> j & 1) { res1 += num[j + y] * num[j + y]; } else { res0 += num[j + y] * num[j + y]; } } if (mp.count(res0 - res1)) { for (auto st : mp[res0 - res1]) { if (__builtin_popcount(i) + __builtin_popcount(st) == y) { print(st, i); return 0; } } } } return 0; }
RC-u4 City 不 City
思路
赛中只拿了 20 分,后来没时间 debug 了,赛后来改了几行就过了 \(\dots\)
很一眼的 \(dijkstra\),但是需要维护路径上的最高热度值,所以添加一个 \(path\) 数组维护路径上除起点和终点以外的最大热度值最小即可。
代码
#include <bits/stdc++.h> using i64 = long long; using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int n, m, s, t; cin >> n >> m >> s >> t; vector<int> a(n + 1); for (int i = 1; i <= n; i ++) { cin >> a[i]; } vector<vector<pair<int, int>>> g(n + 1); for (int i = 0; i < m; i ++) { int u, v, w; cin >> u >> v >> w; g[u].push_back({v, w}); g[v].push_back({u, w}); } vector<int> dis(n + 1, 1e9), path(n + 1); priority_queue<array<int, 2>> Q; dis[s] = 0; Q.push({0, s}); while (Q.size()) { auto [d, u] = Q.top(); Q.pop(); if (dis[u] < d) continue; for (auto [v, w] : g[u]) { if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; Q.push({ -dis[v], v}); if (v != t) { path[v] = max(path[u], a[v]); } else { path[v] = path[u]; } } else if (dis[v] == dis[u] + w) { path[v] = min(max(a[v], path[u]), path[v]); } } } if (dis[t] == 1e9) { cout << "Impossible\n"; } else { cout << dis[t] << ' ' << path[t] << '\n'; } return 0; }
RC-u5 贪心消消乐
思路
唉不太会,听别人说写个二维前缀和暴力都能有 \(24\) 分来着,我后来改了好久也只会 \(22\) 分的,等之后改完了再重新更新下吧。
大概思路就是, \(n^3\) 的前缀和扫描每行的最大子段和 \(dp\),会 wa 第二个和最后一个点,想不明白。
哦对了,这个傻逼题还把行和列反着给,一个样例给我硬控几分钟,wok。
代码
#include <bits/stdc++.h> using i64 = long long; using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; const int inf = -5e5; vector a(n + 1, vector<int>(n + 1)); for (int i = 1; i <= n; i ++) { for (int j = 1; j <= n; j ++) { cin >> a[j][i]; if (!a[j][i]) a[j][i] = inf; } } auto Min = [](array<int, 5> &x, array<int, 5> &y)->array<int, 5> { if (x[0] != y[0]) return x[0] > y[0] ? x : y; if (x[1] != y[1]) return x[1] < y[1] ? x : y; if (x[2] != y[2]) return x[2] < y[2] ? x : y; if (x[3] != y[3]) return x[3] < y[3] ? x : y; return x[4] < y[4] ? x : y; }; int ans = 0; while (true) { // for (int i = 1; i <= n; i ++) // for (int j = 1; j <= n; j ++) // cout << a[i][j] << " \n"[j == n]; array<int, 5> res{inf, 0, 0, 0, 0}; for (int i = 1; i <= n; i ++) { vector<int> pre(n + 1); for (int j = i; j <= n; j ++) { vector<array<int, 2>> dp(n + 1); // cout << i << ' ' << j << ":\n"; for (int k = 1; k <= n; k ++) { pre[k] += a[j][k]; // cout << pre[k] << " \n"[k == n]; } for (int k = 1; k <= n; k ++) { dp[k][1] = k; if (k > 1 && dp[k - 1][0] + pre[k] > dp[k][0]) { dp[k] = dp[k - 1]; } dp[k][0] += pre[k]; array<int, 5> t = {dp[k][0], i, dp[k][1], j, k}; res = Min(res, t); } } } if (res[0] <= 0) { break; } ans += res[0]; auto [v, x1, y1, x2, y2] = res; cout << '(' << x1 << ", " << y1 << ") (" << x2 << ", " << y2 << ") " << v << '\n'; int len = y2 - y1 + 1, no = -1e5; for (int i = x1; i <= x2; i ++) { for (int j = y1; j <= y2; j ++) { a[i][j] = no; } for (int j = n; j >= 1; j --) { if (a[i][j] != no) { int k = j; while (k + 1 <= n && a[i][k + 1] == no) { swap(a[i][k], a[i][k + 1]); k ++; } } } for (int j = 1; j <= n; j ++) { if (!a[i][j]) { a[i][j] = inf; } } } } cout << ans << '\n'; return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18344130
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步