2022 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛)解题报告 | 珂学家


前言

在这里插入图片描述


题解

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;
}


写在最后

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值