2021 RoboCom 世界机器人开发者大赛-本科组(复赛)

7-1 冒险者分队

思路:

\(\qquad\)首先,我们把初始数值与目标数值做差,通过题目的两种操作不难得知,如果差值不是20的倍数那么一定无法成功。

\(\qquad\)同时,我们把差值全部除以20,以简化问题。接着,我们思考一下,我们将三个差值排序之后可以得到 \(diff_1 \lt diff_2 \lt diff_3\) 的排列,而我们的目标也变成了通过最少次操作使这三个差值的关系变为 \(diff_1 = diff_2 = diff_3 = 0\) 而通过这个结果我们倒推可以发现,最终一定是由 \(-1, -1, 2\)\(-2, 1, 1\) 的排列通过操作的来。

\(\qquad\)而此时我们发现,这两种排列的三个数在模 \(3\) 的情况下是相等的,而根据同余原理倒推我们可以发现不论何时他们在模 \(3\) 意义下的结果一定相等。根据这点我们完成了最后的不可行判断。

\(\qquad\)最后,如何来构造最优解呢?首先,我们对 \(diff_2\) 以最少的操作次数置零,然后对于 \(diff_1\) 以及 \(diff_3\) 我们可以通过操作一和操作二混合使用的方式来达到 \(diff_1 + 3, diff_2 + 0, diff_3 - 3\) 的效果,并且可以证明这是最优解。

code:

#include <bits/stdc++.h>

#define int long long

void solve() {
    int a[3], b[3];
    int sum_a = 0, sum_b = 0;
    for(int i = 0; i < 3; i ++ ) {
        std::cin >> a[i];
        sum_a += a[i];
    }
    for(int i = 0; i < 3; i ++ ) {
        std::cin >> b[i];
        sum_b += b[i];
        a[i] -= b[i];
    }

    if(a[0] % 20 || a[1] % 20 || a[2] % 20 || sum_a != sum_b) {
        std::cout << "-1\n";
        return;
    }
    
    a[0] /= 20, a[1] /= 20, a[2] /= 20;

    std::sort(a, a+3);

    int mod = (a[0] % 3 + 3) % 3;
    if((a[1] % 3 + 3) % 3 != mod || (a[2] % 3 + 3) % 3 != mod) {
        std::cout << "-1\n";
        return;
    }

    int ans = 0;
    if(a[1] > 0) {
        ans += a[1], a[2] -= a[1], a[0] += a[1]*2;
    }
    else {
        ans += -a[1], a[0] += -a[1], a[2] += a[1]*2;
    }

    std::cout << ans + (a[2] / 3) * 2 << '\n';
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);std::cout.tie(0);

    int t = 1;
    std::cin >> t;

    while(t -- ) {
        solve();
    }

    return 0;
}

7-2 拼题A打卡奖励

思路:

\(\qquad\)这道题我刚好在校赛出给你们做过,一道很经典的01背包变种,相较于普通的01背包,需要注意的就是因为时间是以秒为单位计数的,所以当枚举时间的时候一定会超时。而我们注意到金币的数据范围非常小,因此我们设 \(f[i]\) 为当枚举到一道题时,得到 \(i\) 枚金币需要花费的最少时间。由此可得转移方程 $$f[i] = min(f[i], f[i-c]+t)$$

code:

#include <bits/stdc++.h>

#define int long long

const int inf = 1e9;

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    
    int n, m;
    std::cin >> n >> m;

    int max = 0;

    std::vector<int> t(n), c(n);
    for(int i = 0; i < n; i ++ ) {
        std::cin >> t[i];
    }
    for(int i = 0; i < n; i ++ ) {
        std::cin >> c[i];
        max += c[i];
    }

    std::vector<int> f(max+1, inf);
    f[0] = 0;
    for(int i = 0; i < n; i ++ ) {
        for(int j = max; j >= c[i]; j -- ) {
            f[j] = std::min(f[j], f[j-c[i]]+t[i]);
        }
    }

    for(int i = max; i >= 0; i -- ) {
        if(f[i] <= m) {
            std::cout << i << '\n';
            return 0;
        }
    }
}

7-3 快递装箱

思路:

\(\qquad\) 一道题目非常繁琐的模拟题,思路都在草稿纸上了:

微信图片_20250708230328

微信图片_20250708230334

code:

#include <bits/stdc++.h>

#define pii std::pair<int, int>
#define fir first
#define sec second

#define all(x) x.begin(), x.end()

std::deque<pii> A, D;
std::queue<pii> B, C;

int n, w_max, w1, w2;
int ans1 = 0, ans2 = 0;
std::vector<int> ans;

void work() {
    if(D.size()) {
        auto top = D.front();
        if(D.size() == 1) {
            if(!top.sec) {
                D.pop_front();
                D.push_front({top.fir, 1});
            }
        }
        else {
            D.pop_front();
            auto next = D.front();
            if(!next.sec && next.fir+top.fir <= w_max) {
                D.pop_front();
                D.push_front({next.fir+top.fir, 1});
            }
            else {
                if(top.fir > w2) ans2 ++;
                else A.push_back(top);
            }
        }
        if(!D.front().sec) {
            top = D.front();
            D.pop_front();
            D.push_front({top.fir, 1});
        }
    }

    if(C.size()) {
        if(C.front().fir > w2 && C.front().sec) ans1 ++;
        else D.push_back(C.front());
        C.pop();
    }

    if(B.size()) {
        if(B.front().fir > w1) C.push({B.front().fir, 1});
        else C.push(B.front());
        B.pop();
    }

    if(A.size()) {
        B.push(A.front());
        A.pop_front();
    }
}

int main() {
    std::cin >> n >> w_max >> w1 >> w2;

    for(int i = 0; i < n; i ++ ) {
        int w;
        std::cin >> w;
        if(A.empty()) A.push_front({w, 0});
        else {
            auto top = A.front();
            if(top.fir+w <= w_max) {
                A.pop_front();
                A.push_front({top.fir+w, 1});
            }
            else {
                A.push_front({w, 0});
            }
        }
        work();
    }

    for(int i = 1; i <= 10010; i ++ ) work();

    while(D.size()) {
        auto top = D.front(); D.pop_front();
        if(top.fir > w2) ans2 ++;
        else A.push_back(top);
    }

    while(A.size()) ans.push_back(A.front().fir), A.pop_front();
    while(B.size()) ans.push_back(B.front().fir), B.pop();
    while(C.size()) ans.push_back(C.front().fir), C.pop();
    while(D.size()) ans.push_back(D.front().fir), D.pop_front();

    std::sort(all(ans));

    std::cout << ans1 << ' ' << ans2 << ' ' << ans.size() << '\n';
    if(ans.size()) for(int i = 0; i < ans.size(); i ++ ) {
        if(i == 0) std::cout << ans[i];
        else std::cout << ' ' << ans[i];
    }
    else {
        std::cout << "None";
    }
}
posted @ 2025-07-08 23:05  算法蒟蒻沐小白  阅读(24)  评论(0)    收藏  举报