2024睿抗机器人开发者大赛CAIP编程技能赛

RC-u1 热҈热҈热҈

分数 10

热҈热҈热҈……最近热得打的字都出汗了!

幸好某连锁餐厅开启了气温大于等于 35 度即可获得一杯免费雪碧的活动。但不知为何,在每个星期四的时候,这个活动会暂停一天……

现在给定连续的若干天的气温情况以及给定的第一天是星期几,请你算出有多少天你可以喝到免费的雪碧,又有多少天是因为星期四而导致你喝不到雪碧的。

输入格式:

输入第一行是两个正整数 N, W (1≤N≤50,1≤W≤7),表示给定连续的 N 天,下面给定的第一天是星期 W(7 等于星期天)。

接下来的一行给出 N 个用一个空格隔开的、小于 60 的整数,第 i 个数表示第 i 天的温度。保证温度大于等于 -273 度。

输出格式:

输出两个数,第一个是你能喝到免费雪碧的天数,第二个是你本来能喝到免费雪碧、但因为是星期四而无法喝到的天数。

输入样例:

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

 AC代码,一周7天当是周日的时候,把k == 0就ok

#include<bits/stdc++.h>

using namespace std;

int main(){
    int n, k;
    cin >> n >> k;
    if(k == 7)
        k = 0;
    int cnt1 = 0, cnt2 = 0;
    for(int i = k; i < n + k; i++){
        int x;
        cin >> x;
        if(x >= 35){
            cnt1++;
            if(i % 7 == 4)
                cnt2 ++;
        }
    }
    cout << cnt1 - cnt2 << " " << cnt2;
    return 0;
}

RC-u2 谁进线下了?

分数 15

Xepa Legends 是一个第一人称射击类大逃杀(“吃鸡”)游戏,每轮游戏共有 20 支 3 人小队参加,最后获胜的队伍被称为“捍卫者”。

最近 Xepa Legends 举行了亚太地区南赛区的线上比赛,争夺 7 个前往德国曼海姆参加线下赛的资格,国内共有 14 支队伍参与到了其中。因为比赛十分激烈,直到最后谁进了线下仍有巨大的疑问。小 K 喜欢的国内知名战队 DreamTear 因其队内选手杀马特表现不佳,正好卡在出线分数前后,请你赶紧帮帮小 K,计算一下最后的分数情况,看看他喜欢的战队出线了没有吧!

Xepa Legends 的比赛共进行 N 场游戏,在每场游戏中,每支队伍在游戏中会获得一个排名和一个杀敌数(击败其他队伍玩家的数量),一支队伍在一场游戏的得分为杀敌数+排名分,排名分由队伍当场的排名根据以下表格求得:

排名分数
第一名12 分
第二名9 分
第三名7 分
第四名5 分
第五名4 分
第六名至第七名3 分
第八名至第十名2 分
第十一名至第十五名1 分
第十六名至第二十名0 分

例如,

  • DreamTear 战队在第三场比赛获得了第三名、有 6 个杀敌数,那么他们将获得 7 + 6 = 13 分;
  • KV 战队在第二场比赛获得了第 19 名、有 1 个杀敌数,那么他们将获得 0 + 1 = 1 分;
  • SRN 战队在第四场比赛获得了第 1 名、有 9 个杀敌数,那么他们将获得 12 + 9 = 21 分。

注:本题与实际情况无关,所有比赛规则、队伍、队员名称均为虚构。

输入格式:

输入第一行是一个正整数 N (≤20),表示有 N 场比赛。

接下来有 N 部分输入,每部分是一场比赛的情况。对每一场比赛,信息共分 20 行,第 i 行(i=1,⋯,20)给出的两个非负整数 p 和 k 表示第 i 支队伍在这场比赛里获得了第 p 名、杀敌数为 k。

数据保证所有给定的情况中,排名永远大于等于 1 且小于等于 20,杀敌数小于等于 57。

输出格式:

输出 20 行,按编号从小到大依次输出队伍的编号及该队全部游戏结束时的总分。

输入样例:

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>

using namespace std;

int main(){
    int n;
    cin >> n ;
    vector<int> v = {12, 9, 7, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1};
    v.resize(20);
    vector<pair<int,int>> s(20);
    for(int i = 0; i < n; i ++){
        for(int j = 0; j < 20; j ++){
            int a, b;
            cin >> a >> b;
            s[j].first += (v[a - 1] + b);
            s[j].second = j;
        }
    }
    for(auto [x, y] : s){
        cout << y + 1 << " " << x << endl;
    }
    return 0;
}

 

RC-u3 暖炉与水豚

PapiCon(@PapilloteContet)出了许多有意思的谜题,其中有一道关于水豚的谜题是这样的:

GGwLLL_bwAA8cC4.jpeg


来源:x.com/PapilloteContet

在一个 N×M 的矩阵中有若干水豚以及暖炉,暖炉可以辐射以它自身为中心的 3×3 范围里的水豚,使其变得暖呼呼的。谜题里存在一只冷的要命的水豚,你需要移动其中的一个暖炉,使所有水豚都变得暖呼呼的。

在往下读题前,如果你有兴趣的话,不妨思考一下如何解答这个谜题。(思考结果与题目无关,可跳过。)

这个谜题的关键在于,单纯从图中能看到的暖炉来说是无解的,但如果注意到,第 3 行第 6 列的水豚明明周围没有暖炉,却也处于暖呼呼的状态,就能推测出来图中的那个对话框挡住了一个暖炉,只要移动这个暖炉就可以完成题目的要求。

现在我们将谜题一般化,对于给定的一个 N×M 的矩阵、对应的所有水豚状态、以及能看到的暖炉摆放情况,已知最多只有一只水豚的状态不太对劲(周围没有暖炉却暖呼呼的),你需要推测有哪些格子可能藏了暖炉。一个空格可能藏了暖炉可以理解为:当前空格设置暖炉后整个矩阵的状态会从不合法变为合法。

输入格式:

输入第一行是两个正整数 N, M (1≤N,M≤1000),表示矩阵的大小。

接下来的 N 行,每行有 M 个字符,第 i 行的第 j 个字符表示矩阵中对应位置的状态,其中:

  • . 表示空格(或者说,看上去是空格的格子);
  • c 表示很冷的水豚;
  • w 表示暖呼呼的水豚;
  • m 表示暖炉。

输出格式:

输出若干行,每行两个正整数 r 和 c,表示第 r 行第 c 列有可能藏了一个暖炉,有多个可能时,先按 r 从小到大输出,r 相同时再按 c 从小到大输出。如果没有一个格子可能藏了暖炉, 则在一行中输出Too cold!
行与列均从 1 开始编号。

输入样例:

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

输出样例:

2 7
3 5
4 6
4 7

 题目只说当只有w的时候只有异常,通过c可以确定剩下暖壶可能存在的位置,再判断w的是否合法

#include<bits/stdc++.h>

using namespace std;

int main(){
    int n, m;
    cin >> n >> m;
    vector<vector<char>> v(n, vector<char>(m));
    int xx[8] = {0, 0, -1, 1, -1, -1, 1, 1 };
    int yy[8] = {-1, 1, 0, 0, -1, 1, -1, 1 };
    for(int i = 0; i < n; i ++){
        for(int j = 0; j < m; j ++)
            cin >> v[i][j];
    }
    for(int i = 0; i < n; i ++){
        for(int j = 0; j < m; j ++){
            if(v[i][j] == 'c'){
                for(int k = 0; k < 8; k ++){
                    int x = i + xx[k];
                    int y = j + yy[k];
                    if(x >= 0 && x < n && y >= 0 && y < m && v[x][y] == '.')
                        v[x][y] = 'o';
                }
            }
        }
    }
    vector<pair<int, int>> res;
    for(int i = 0; i < n; i ++){
        for(int j = 0; j < m; j ++){
            if(v[i][j] == 'w'){
                for(int k = 0; k < 8; k ++){
                    int x = i + xx[k];
                    int y = j + yy[k];
                    if(x >= 0 && x < n && y >= 0 && y < m){
                        if(v[x][y] == '.')
                            res.push_back({x, y});
                        else if(v[x][y] == 'm'){
                            res.clear();
                            break;
                        }
                    }
                }
                if(res.size()){
                    sort(res.begin(), res.end());
                    for(auto [x, y] : res)
                        cout << x + 1<< " " << y + 1<< endl;
                    return 0;
                }
            }
        }
    }
    cout << "Too cold!";
    return 0;
}

 

RC-u4 章鱼图的判断

对于无向图 G=(V,E),我们将有且只有一个环的、大于 2 个顶点的无向连通图称之为章鱼图,因为其形状像是一个环(身体)带着若干个树(触手),故得名。

给定一个无向图,请你判断是不是只有一个章鱼子图存在。

输入格式:

输入第一行是一个正整数 T (1≤T≤5),表示数据的组数。

每组数据的第一行是两个正整数 N,M (1≤N,M≤105),表示给定的无向图有 N 个点,M 条边。

接下来的 M 行,每行给出一条边两个端点的顶点编号。注意:顶点编号从 1 开始,并且题目保证任何边不会重复给出,且没有自环。

输出格式:

对于每组数据,如果给定的图里只有一个章鱼子图,则在一行中输出 Yes 和章鱼子图环的大小(及环中顶点数),其间以 1 个空格分隔。

否则,则在一行中输出 No 和图中章鱼子图的个数,其间以 1 个空格分隔。

输入样例:

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

 把路径记录下来,当找到一个已经被遍历的node,只要这个node不是路径的上一个点,只要是如图所示的环就没有问题,当一个图中可能存在两个环,需要判断一下,但只得到17分,求高手指点

#include<bits/stdc++.h>

using namespace std;

#define pd push_back
#define ppb pop_back
void solve(){
    int n, m;
    cin >> n >> m;
    vector<vector<int>> v(n + 1);
    for(int i = 0; i < m; i ++){
        int a, b;
        cin >> a >> b;
        v[a].pd(b);
        v[b].pd(a);
    }
    vector<int> path;
    vector<int> res;
    vector<bool> st(n + 1, false);
    auto check = [&](int x) -> int{
        int len = path.size();
        for(int j = 0; j < len - 2; j ++){
            if(path[j] == x)
                return j;
        }
        return -1;
    };
    function<void(int, vector<int>&)> dfs = [&](int a,  vector<int> &path) -> void{
        path.pd(a);
        st[a] = true;
        int l = v[a].size();
        for(int i = 0; i < l; i ++){
            int len = path.size();
            if(st[v[a][i]] && len > 1 && path[len - 2] != v[a][i]){
                int t = check(v[a][i]);
                // if(t != 0)
                res.pd(path.size() - t);
            }else if(!st[v[a][i]]){
                dfs(v[a][i], path);
            }
        }
        path.ppb();
        return ;
    };
    for(int i = 1; i <= n; i ++){
        if(!st[i]){
            int t = res.size();
            dfs(i, path);
            if(res.size() - t > 1)
                res.erase(res.begin() + t, res.end());
        }
    }
    if(res.size() == 1)
        cout << "Yes" << " " << res[0] << endl;
    else{
        cout << "No" << " ";
        cout << res.size() << endl;
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++)
        solve();
    return 0;
}

 

RC-u5 工作安排

小 K 有 N 项工作等待完成,第 i 项工作需要花 ti​ 单位时间,必须在 di​ 时刻或之前完成,报酬为 pi​。假设小 K 工作时刻从 0 开始,且同一时刻只能做一项工作、工作一旦开始则不可中断或切换至其他工作,请你帮小 K 规划一下如何选择合适的工作,使小 K 可以获得最多的报酬。

输入格式:

输入第一行是一个正整数 T (≤5),表示数据的组数。

接下来有 T 组数据,每组数据第一行是一个正整数 N (≤5000),表示待完成工作的数量。接下来的 N 行,每行三个非负整数 ti​、di​、pi​ (均 ≤5000;1≤i≤N),表示第 i 项工作需要花费的时间、截止时间以及报酬。

输出格式:

对于每组数据,输出小 K 能获得最多的报酬是多少。

输入样例:

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

 一眼dp,状态是时间,但需要对截止时间从小到大进行排序,否则会稍加,达不到最优条件

如果不进行排序,那么如果红色部分在前面,则蓝色部分的值就会舍弃,不知最优结果

 

#include <bits/stdc++.h>

using namespace std;

#define MAX_TIME 5000

struct Job {
    int t; // 花费时间
    int d; // 截止时间
    int p; // 报酬

    Job(int t, int d, int p) : t(t), d(d), p(p) {}
};

void solve() {
    int n;
    cin >> n;

    vector<Job> jobs;
    for (int i = 0; i < n; ++i) {
        int t, d, p;
        cin >> t >> d >> p;
        jobs.emplace_back(t, d, p);
    }

    // 按截止时间升序排序
    sort(jobs.begin(), jobs.end(), [](const Job& a, const Job& b) {
        return a.d < b.d;
    });

    // dp数组初始化
    vector<int> dp(MAX_TIME + 1, 0);

    // 处理每个工作
    for (const auto& job : jobs) {
        int t = job.t;
        int d = job.d;
        int p = job.p;

        // 逆序更新dp数组,确保每个工作只被考虑一次
        for (int j = d; j >= t; --j) {
            dp[j] = max(dp[j], dp[j - t] + p);
        }
    }

    // 计算最大报酬
    int max_profit = *max_element(dp.begin(), dp.end());
    cout << max_profit << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int T;
    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值