2024 睿抗機器人開發者大賽CAIP-程式設計技能賽-本科組(省賽)

KXDdesu發表於2024-07-20

寫在前面

程式碼需要手動展開!!!
比賽前,好久沒有刷題,一直準備期末考試
比賽前一天才剛到家
15號中午匆匆忙忙的開始比賽
2點開始的時候,oms伺服器直接崩了,本來以為是當時打GPLT時安裝的oms版本不相容CAIP
心想,這不開局就寄了
還好是都崩了,不是我自己的問題
第一個小時
T1,T2,T3都很快寫完
看到T4後,感覺是個hard題就先跳了
T5,剛開始想的是貪心,後來發現不太對,不能直接排序後就計算,就先寫了一個dfs,拿了一部分分,然後發現是個01揹包,改成貪心排序+dp就過了
第二個小時
寫了一個小時的T4
剛開始想的是無向圖的雙連通分量,但是模板已經忘了
畫了畫樣例的圖,發現用dfs+時間戳貌似可以解決
結果調了半個小時,還有最好兩分鐘的時候才A了
最後一分鐘,伺服器再次崩潰,但凡晚交一會兒,都AK不了
總結:這次CAIP發揮的還不錯,名次最低也才400名

T1

輸入樣例:

15 3
33 35 34 36 37 40 32 31 30 29 28 29 33 38 40

輸出樣例:

5 1

直接遍歷一下天數,判斷每天的溫度和周幾

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int n, w;
    std::cin >> n >> w;
    int c1 = 0, c2 = 0;
    for (int i = 0; i < n; i ++) {
        int x;
        std::cin >> x;
        if (x >= 35) {
            if (w == 4) {
                c2 ++;
            }
            else {
                c1 ++;
            }
        }
        w = (w + 1) % 7;
        if (w == 0) {
            w = 7;
        }
    }
    std::cout << c1 << ' ' << c2 << '\n';
}
int main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    //std::cin >> T;
    while (T --) solve();
    return 0;
}

T2

輸入樣例:

3
6 2
7 3
11 5
10 1
2 9
5 8
14 3
4 3
1 6
18 1
12 1
20 0
13 0
3 2
16 4
8 1
19 0
9 4
17 1
15 0
8 2
19 1
12 2
1 9
10 1
7 5
18 0
14 0
5 2
4 4
2 5
6 2
16 3
13 1
20 0
3 7
9 3
15 0
17 5
11 3
18 0
5 2
2 9
9 4
4 7
10 3
16 0
1 6
20 0
15 1
6 0
3 6
14 3
7 4
19 0
17 0
8 9
11 0
13 5
12 0

輸出樣例:

1 9
2 13
3 27
4 30
5 33
6 25
7 4
8 27
9 24
10 12
11 19
12 18
13 8
14 18
15 4
16 17
17 16
18 8
19 12
20 6

按給出的排名分和殺敵數,算一下每隊每場的分數,累加起來,輸出即可

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
int p[21] = {0, 12, 9, 7, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
void solve()
{
    std::vector<int> a(20);
    int n;
    std::cin >> n;
    while (n --) {
        for (int i = 0; i < 20; i ++) {
            int x, v;
            std::cin >> x >> v;
            a[i] += p[x] + v;
        }
    } 
    for (int i = 0; i < 20; i ++) {
        std::cout << i + 1 << ' ' << a[i] << '\n';
    }
}
int main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    //std::cin >> T;
    while (T --) solve();
    return 0;
}

T3


輸入樣例:

6 8
wm....mw
.w..ww..
..wm.wwm
w.w....w
.m.c.m..
w.....w.

輸出樣例:

2 7
3 5
4 6
4 7

暴力列舉即可
先判斷所有溫暖的水豚,誰可能擋住暖爐
若有可能擋住暖爐的水豚,判斷周邊的空地,哪些可以放置
最後將答案直接輸出即可,注意若沒有可以放置的空地,就輸出”Too cold!"

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int n, m;
    std::cin >> n >> m;
    std::vector<std::string> g(n);
    for (int i = 0; i < n; i ++) {
        std::cin >> g[i];
    }
    int nx = -1, ny = -1;
    auto check1 = [&](int x, int y) -> bool {
        for (int i = -1; i <= 1; i ++) {
            for (int j = -1; j <= 1; j ++) {
                if (i == 0 && j == 0) {
                    continue;
                }
                int a = x + i;
                int b = y + j;
                if (a < 0 || a >= n || b < 0 || b >= m) {
                    continue;
                }
                if (g[a][b] == 'm') {
                    return false;
                }
            }
        }
        return true;
    };
    for (int i = 0; i < n; i ++) {
        for (int j = 0; j < n; j ++) {
            if (g[i][j] == 'w' && check1(i, j)) {
                nx = i;
                ny = j;
            }
        }
    }
    if (nx == -1 && ny == -1) {
        std::cout << "Too cold!\n";
    }
    else {
        auto check2 = [&](int x, int y) -> bool {
            for (int i = -1; i <= 1; i ++) {
                for (int j = -1; j <= 1; j ++) {
                    if (i == 0 && j == 0) {
                        continue;
                    }
                    int a = x + i;
                    int b = y + j;
                    if (a < 0 || a >= n || b < 0 || b >= m) {
                        continue;
                    }
                    if (g[a][b] == 'c') {
                        return false;
                    }
                }
            }
            return true;
        };
        std::vector<pii> ans;
        for (int i = -1; i <= 1; i ++) {
            for (int j = -1; j <= 1; j ++) {
                if (i == 0 && j == 0) {
                    continue;
                }
                int a = nx + i;
                int b = ny + j;
                if (a < 0 || a >= n || b < 0 || b >= m) {
                    continue;
                }
                if (g[a][b] == '.') {
                    if (check2(a, b)) {
                        ans.push_back({a, b});
                    }
                }
            } 
        } 
        std::sort(all(ans));
        if (ans.size() == 0) {
            std::cout << "Too cold!\n";
        }
        else {
            for (auto [x, y] : ans) {
                std::cout << x + 1 << ' ' << y + 1 << '\n';
            }
        }
    }
}
int main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    //std::cin >> T;
    while (T --) solve();
    return 0;
}

T4

輸入樣例:

3
10 10
1 3
3 5
5 7
7 9
1 2
2 4
2 6
3 8
9 10
1 9
10 10
1 3
3 5
5 7
7 9
9 1
1 2
2 4
4 8
8 10
10 1
10 10
1 3
3 5
5 7
7 9
9 1
2 4
4 8
8 10
10 2
10 6

輸出樣例:

Yes 5
No 0
No 2

畫一畫樣例,可以發現先用dfs+時間戳
找到每個子圖一共有幾個環
若只有一個章魚子圖,然後從這個子圖的任意節點進行dfs,統計前驅節點數量
成環時,進行相減,即可算出環中節點數量。

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
void solve()
{
    int n, m;
    std::cin >> n >> m;
    std::vector<std::vector<int>> adj(n);
    for (int i = 0; i < m; i ++) {
        int u, v;
        std::cin >> u >> v;
        u --;
        v --;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    int cnt1 = 0;
    int root = -1;
    int time = 0;
    std::vector<int> st(n);
    std::vector<int> dfn(n, -1);
    auto dfs1 = [&](auto dfs1, int u, int fa) -> void {
        if (st[u]) {
            return;
        }
        // std::cerr << u << '\n';
        st[u] = true;
        dfn[u] = time ++;
        for (auto v : adj[u]) {
            if (v == fa) {
                continue;
            } 
            if (dfn[v] != -1 && dfn[v] < dfn[u]) {
                cnt1 ++;
                continue;
            }
            dfs1(dfs1, v, u);
        }
    };
    int cnt = 0;
    for (int i = 0; i < n; i ++) {
        if (st[i]) {
            continue;
        }
        dfs1(dfs1, i, -1);
        // std::cerr << '\n';
        // std::cerr << i << ' ' << cnt1 << '\n';
        if (cnt1 == 1) {
            cnt ++;
            root = i;
        }
        cnt1 = 0;
    }
    if (cnt == 1) {
        std::vector<int> ct(n);
        std::vector<int> st2(n);
        int cnt2 = 0;
        ct[root] = 1;
        auto dfs2 = [&](auto dfs2, int u, int fa) -> void {
            if (st2[u]) {
                return;
            }
            st2[u] = true;
            for (auto v : adj[u]) {
                if (v == fa) {
                    continue;
                }
                if (dfn[v] < dfn[u]) {
                    cnt2 = ct[u] - ct[v] + 1;
                }
                ct[v] = ct[u] + 1;
                dfs2(dfs2, v, u);
            }
        };
        dfs2(dfs2, root, -1);
        std::cout << "Yes " << cnt2 << '\n';
    }
    else {
        std::cout << "No " << cnt << '\n';
    }
}
int main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    std::cin >> T;
    while (T --) solve();
    return 0;
}

T5

輸入樣例:

3
5
1 2 50
3 3 100
1 5 1
3 2 5000
4 5 30
5
1 2 50
3 3 20
1 5 1
3 2 5000
4 5 30
5
1 2 50
3 3 100
1 5 1
3 2 5000
5 5 800

輸出樣例:

101
80
800

先根據截止時間,再根據所需時長,最後根據價值進行貪心排序
然後再進行01揹包,即可得到答案

點選檢視程式碼
#include<bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define fi first
#define se second
#define lowbit(x) (x) & (-x)
using i64 = long long;
using pii = std::pair<int, int>;
struct T5
{
    int t, d, p;
};
void solve()
{
    int n;
    std::cin >> n;
    std::vector<T5> a;
    for (int i = 0; i < n; i ++) {
        int t, d, p;
        std::cin >> t >> d >> p;
        if (t > d) {
            continue;
        }
        a.push_back({t, d, p});
    }
    n = a.size();
    std::sort(all(a), [&](T5 x, T5 y){
        if (x.d != y.d) {
            return x.d < y.d;
        }
        if (x.t != y.t) {
            return x.t < y.t;
        }
        return x.p > y.p;
    });
    std::vector<int> f(5010);
    for (int i = 0; i < n; i ++) {
        auto [t, d, p] = a[i];
        for (int T = d; T >= t; T --) {
            f[T] = std::max(f[T], f[T - t] + p);
        }
    }
    int max = 0;
    for (int i = 0; i <= 5000; i ++) {
        max = std::max(max, f[i]);
    }
    std::cout << max << '\n';
}
int main()
{
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int T = 1;
    std::cin >> T;
    while (T --) solve();
    return 0;
}

相關文章