前言
题解
2022 RoboCom 世界机器人开发者大赛-本科组(国赛)。
第五题挺难得,数据弱了,这个比赛的签到题也不好写,需要有足够的耐心。
RC-u1 智能红绿灯
分值: 15分
引入4个状态
- 绿色
- 绿色-红色 中间态
- 红色
- 红色-红色,不允许延长
这题看着简单,实际不好写。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> arr(n);
for (int &x: arr) cin >> x;
// 最暴力的模拟
int N = 10000 + 100;
vector<int> span(N, 0);
// 0: 绿色, 1: 绿-红(15), 2: 红, 3:double红
for (int v: arr) {
if (span[v] == 0) {
for (int j = 0; j < 15; j++) {
span[v + j] = 1;
}
for (int j = 15; j < 45; j++) {
span[v + j] = 2;
}
} else if (span[v] == 2) {
int j = v;
while (span[j] == 2) {
span[j] = 3;
j++;
}
for (int k = 0; k < 15; k++) {
span[j + k] = 3;
}
}
}
int i = 0;
while (i < N) {
if (span[i] < 2) {
i++;
continue;
}
int j = i + 1;
while (j < N && span[j] >= 2) {
j++;
}
cout << i << " " << (j - 1) << "\n";
i = j;
}
return 0;
}
RC-u2 女王的大敕令
分值: 20分
思路: 逆向dfs
#include <bits/stdc++.h>
using namespace std;
int main() {
int c1, c2, r1, r2;
cin >> c1 >> c2 >> r1 >> r2;
int x1, x2, x3, x4;
cin >> x1 >> x2 >> x3 >> x4;
int row, col, d1, d2;
cin >> row >> col >> d1 >> d2;
vector<array<int, 4>> ans;
function<void(int,int,int)> dfs;
dfs = [&](int idx, int py, int px) {
int rvis[6] = {0};
int cvis[6] = {0};
if (idx == 1) {
cvis[c1] = 1;
cvis[c2] = 1;
rvis[r1-x3] = 1;
rvis[r2+x4] = 1;
} else {
cvis[c1+x1] = 1;
cvis[c2-x2] = 1;
rvis[r1-x3] = 1;
rvis[r2+x4] = 1;
}
int dist = (idx == 0) ? d2 : d1;
for (int i = 1; i <= 5; i++) {
if (rvis[i] == 1) continue;
for (int j = 1; j <= 5; j++) {
if (cvis[j] == 1) continue;
int d = abs(i - py) + abs(j - px);
if (d == dist) {
if (idx == 0) {
dfs(idx + 1, i, j);
} else {
ans.push_back({i, j, py, px});
}
}
}
}
};
dfs(0, row, col);
sort(ans.begin(), ans.end());
for (auto &e: ans) {
cout << e[0] << " " << e[1] << " " << e[2] << " " << e[3] << "\n";
}
return 0;
}
RC-u3 战利品分配
分值: 25分
思路: PTA 的传统节目,二元组的Dijkstra
#include <bits/stdc++.h>
using namespace std;
struct P {
int u, w, c;
P(int u, int w, int c) : u(u), w(w), c(c) {}
bool operator<(const P &lhs) const {
if (w != lhs.w) return w < lhs.w;
return c < lhs.c;
}
};
int main() {
int n, m, k, p;
cin >> n >> m >> k >> p;
p--;
vector<int> wv(n);
for (int &x: wv) cin >> x;
vector<vector<int>> g(n);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
u--; v--;
g[u].push_back(v);
g[v].push_back(u);
}
int s, t;
cin >> s >> t;
s--; t--;
const int inf = 0x3f3f3f;
vector<array<int, 2>> dp(n, {inf, inf});
auto comp = [](auto &a, auto &b) { return b < a; };
priority_queue<P, vector<P>, decltype(comp)> pq;
int ws = (p % k == 0) ? wv[s] : 0;
dp[s] = {0, ws};
pq.push(P(s, 0, ws));
while (!pq.empty()) {
P cur = pq.top(); pq.pop();
int u = cur.u;
if (cur.w > dp[u][0] || (cur.w == dp[u][0] && cur.c < dp[u][1])) continue;
for (int v: g[u]) {
int delta = ((cur.w + 1) % k == p) ? wv[v] : 0;
if (dp[v][0] > dp[u][0] + 1) {
dp[v][0] = dp[u][0] + 1;
dp[v][1] = dp[u][1] + delta;
pq.push(P(v, dp[v][0], dp[v][1]));
} else if (dp[v][0] == dp[u][0] + 1 && dp[v][1] < dp[u][1] + delta) {
dp[v][1] = dp[u][1] + delta;
pq.push(P(v, dp[v][0], dp[v][1]));
}
}
}
cout << dp[t][1] << "\n";
return 0;
}
RC-u4 变牛的最快方法
分值: 30分
思路: 动态规划
这题本质上就是典题: 编辑距离
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> arr, brr;
int v;
while ((cin >> v) && v != -1) {
arr.push_back(v);
}
while ((cin >> v) && v != -1) {
brr.push_back(v);
}
int n = arr.size(), m = brr.size();
const int inf = 0x3f3f3f3f;
vector<vector<int>> dp(n+1, vector<int>(m+1, inf));
vector<vector<array<int, 2>>> source(n + 1, vector<array<int, 2>>(m + 1, {-1, -1}));
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
dp[i][0] = dp[i - 1][0] + 1;
source[i][0] = {i - 1, 0};
}
for (int j = 1; j <= m; j++) {
dp[0][j] = dp[0][j - 1] + 1;
source[0][j] = {0, j - 1};
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (arr[i - 1] == brr[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
source[i][j] = {i - 1, j - 1};
} else {
if (dp[i][j] > dp[i - 1][j - 1] + 1) {
// change
dp[i][j] = dp[i - 1][j - 1] + 1;
source[i][j] = {i - 1, j - 1};
}
if (dp[i][j] > dp[i - 1][j] + 1) {
// del
dp[i][j] = dp[i - 1][j] + 1;
source[i][j] = {i - 1, j};
}
if (dp[i][j] > dp[i][j - 1] + 1) {
// add
dp[i][j] = dp[i][j - 1] + 1;
source[i][j] = {i, j - 1};
}
}
}
}
cout << dp[n][m] << "\n";
vector<int> ops;
int y = n, x = m;
while (y != 0 || x != 0) {
auto [y1, x1] = source[y][x];
if (y == y1 + 1 && x == x1 + 1) {
if (dp[y][x] == dp[y1][x1]) {
ops.push_back(2);
} else {
ops.push_back(1);
}
} else if (y == y1 + 1 && x == x1) {
ops.push_back(0);
} else {
ops.push_back(3);
}
y = y1; x = x1;
}
reverse(ops.begin(), ops.end());
for (int i = 0; i < ops.size(); i++) {
cout << ops[i];
}
cout << "\n";
return 0;
}
RC-u5 养老社区
分值:30分
OJ的数据弱了, O ( n 3 ) O(n^3) O(n3)能拿满分,不应该。
正解,应该是基于bitset优化的枚举。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<vector<int>> g(n);
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
u--; v--; // index-1 -> index-0
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> vw(n);
for (int &x: vw) cin >> x;
int inf = 0x3f3f3f;
vector<vector<int>> path(n, vector<int>(n, inf));
function<void(int)> bfs = [&](int u) {
vector<int> dp(n, inf);
path[u][u] = 0;
dp[u] = 0;
deque<int> que;
que.push_back(u);
while (!que.empty()) {
int v = que.front(); que.pop_front();
path[u][v] = dp[v];
for (int w: g[v]) {
if (dp[w] > dp[v] + 1) {
dp[w] = dp[v] + 1;
que.push_back(w);
}
}
}
};
for (int i = 0; i < n; i++) bfs(i);
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (vw[i] == vw[j]) continue;
for (int k = j + 1; k < n; k++) {
if (path[i][j] == path[i][k] && path[i][j] == path[j][k]) {
if (vw[i] != vw[j] && vw[i] != vw[k] && vw[j] != vw[k]) {
ans ++;
}
}
}
}
}
cout << ans << "\n";
return 0;
}