跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

2025 年睿抗机器人开发者大赛 CAIP 编程技能赛本科组解题报告

2025 年睿抗机器人开发者大赛 CAIP 编程技能赛本科组国赛复盘。涵盖哈希表统计、网格模拟、字符串栈处理、二分结合最短路以及区间动态规划等核心算法。重点解析了各题的关键逻辑与易错点,如操作累加除二、坐标偏移匹配、删除次数统计、费用限制下的最短路径及合并代价计算。提供完整 C++ 参考代码,帮助理解解题思路与实现细节。

女王发布于 2026/4/11更新于 2026/7/2539 浏览
2025 年睿抗机器人开发者大赛 CAIP 编程技能赛本科组解题报告

前言

2025 年睿抗机器人开发者大赛 CAIP-编程技能赛本科组国赛复盘。本届比赛代码量依然可观,对细节把控要求较高,需要扎实的算法基础与编码能力。

题解

RC-u1 谁拿冠军了?

分值:15 分 考察点:哈希表统计

这道题的核心在于处理同一天内可能存在的多个相同操作。题目要求求和后再除 2,这里有个坑需要注意:如果某天有重复操作,直接累加再统一计算逻辑会更稳妥。

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n, m; cin >> n >> m;
    int A1, A2, B1, B2, B3; cin >> A1 >> A2 >> B1 >> B2 >> B3;
    // 利用 array<int, 2> 表示二元组 (d,op)
    map<array<int,2>,int> ops;
    for(int i = 0; i < n; i++){
        int d, op; cin >> d >> op;
        ops[{d, op}] += 1;
    }
    // 题意保证 一天最多一个操作
    map<int,int> ban;
    for(int i = 0; i < m; i++){
        int t, op; cin >> t >> op;
        ban[t] = op;
    }
    int sw1 = 0, sw2 = 0;
    for(auto[k, cnt]: ops){
        auto[d, op] = k;
        // 减半影响的操作
        if(ban.count(d) && ban[d] == op){
            if(op == 1){ sw1 += A1 * cnt; sw2 -= B1 * cnt / 2; }
            else if(op == 2){ sw2 -= B2 * cnt / ; }
             (op == ){ sw1 -= A2 * cnt; sw2 -= B3 * cnt / ; }
        }  {
            (op == ){ sw1 += A1 * cnt; sw2 -= B1 * cnt; }
             (op == ){ sw2 -= B2 * cnt; }
             (op == ){ sw1 -= A2 * cnt; sw2 -= B3 * cnt; }
        }
    }
    cout << sw1 <<  << sw2 << ;
     ;
}
2
else
if
3
2
else
if
1
else
if
2
else
if
3
" "
"\n"
return
0

RC-u2 理包

分值:20 分 思路:模拟

枚举包裹的空坐标,然后以物品坐标系,以相对偏移向量尝试填充匹配。感觉码量有点大,看起来简单,但写起来稍头痛。注意边界检查。

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n, m, q; cin >> n >> m >> q;
    vector<string>g(n);
    for(int i = 0; i < n; i++){ g[i].resize(m,'.'); }
    while(q-->0){
        int r, c; cin >> r >> c;
        vector<string>mat(r);
        int sy = -1, sx = -1;
        for(int i = 0; i < r; i++){
            cin >> mat[i];
            if(sy == -1){
                for(int j = 0; j < c; j++){
                    if(mat[i][j]=='*'){ sy = i; sx = j; break; }
                }
            }
        }
        // 以物品坐标去匹配包裹,oy/ox是相对偏移向量
        auto check =[&](int oy,int ox)->bool{
            for(int i = 0; i < r; i++){
                for(int j = 0; j < c; j++){
                    if(mat[i][j]=='*'){
                        if(i + oy >=0&& i + oy < n && j + ox >=0&& j + ox < m){
                            if(g[i + oy][j + ox]=='*'){return false;}
                        }else{return false;}
                    }else{return false;}
                }
            }
            return true;
        };
        // 以物品坐标去填充包裹,oy/ox是相对偏移向量
        auto fill =[&](int oy,int ox){
            for(int i = 0; i < r; i++){
                for(int j = 0; j < c; j++){
                    if(mat[i][j]=='*'){ g[i + oy][j + ox]='*'; }
                }
            }
        };
        // 从包裹坐标出发,寻找空格去,查询是否放入物品
        auto solve =[&](int&ay,int&ax)->bool{
            for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                    if(g[i][j]=='.'){
                        if(check(i - sy, j - sx)){ ay = i; ax = j;fill(i - sy, j - sx);return true; }
                    }
                }
            }
            return false;
        };
        int ay = 0, ax = 0;
        if(solve(ay, ax)){ cout <<(ay +1)<< " " <<(ax +1)<< "\n"; }
        else{ cout <<-1<< " " <<-1<< "\n"; }
    }
    return 0;
}

RC-u3 删除屏蔽词

分值:25 分 思路:模拟 + 栈

这题限定模式串固定为 2,如果为 k,那这题就麻烦了。就是当前字符,以及栈顶元素,是否构成模式串。注意:需要输出删除次数,不是最后文本的长度。

#include<bits/stdc++.h>
using namespace std;

int main(){
    string p; string s;
    getline(cin, p);
    getline(cin, s);
    int del = 0;
    stack<char> stk;
    for(char c: s){
        // 核心代码,就是这一行
        if(c == p[1]&&!stk.empty()&& stk.top()== p[0]){ stk.pop(); del++; }
        else{ stk.push(c); }
    }
    string buf;
    while(!stk.empty()){ buf.push_back(stk.top()); stk.pop(); }
    reverse(buf.begin(), buf.end());
    cout << del << " " << buf << "\n";
    return 0;
}

RC-u4 穷游

分值:30 分 思路:二分 + dijkstra

可以先确定最小的住宿费用,再求解此基础上的最小时长。这个套路,在睿抗编程赛中,多次出现。二分 check 的核心逻辑是连通性,为了简化代码,可以复用带限制的求时长 dijkstra。这样在追求编码效率和代码 AC 之间达到一个好的平衡。

#include<bits/stdc++.h>
using namespace std;
struct E{int v, w;E(){}E(int v,int w):v(v),w(w){}};
struct P{int u, c;P(){}P(int u,int c):u(u),c(c){}};

int main(){
    int n, m; cin >> n >> m;
    vector<int>prices(n);
    for(int&x: prices) cin >> x;
    vector<vector<E>>g(n);
    for(int i = 0; i < m; i++){
        int u, v, w; cin >> u >> v >> w;
        u--; v--;
        g[u].push_back(E(v, w)); g[v].push_back(E(u, w));
    }
    int s, e; cin >> s >> e; s--; e--;
    auto comp =[](const P&lhs,const P&rhs){return lhs.c > rhs.c;};
    int inf = 0x3f3f3f3f;
    auto dijkstra =[&](int limit){
        vector<int>dp(n, inf); dp[s]=0;
        priority_queue<P, vector<P>,decltype(comp)>pq(comp);
        pq.push(P(s,0));
        while(!pq.empty()){
            P p = pq.top(); pq.pop();
            if(p.c > dp[p.u])continue;
            if(p.u == e){return p.c;}
            for(E &e: g[p.u]){
                if(prices[e.v]> limit)continue;
                if(dp[e.v]> p.c + e.w){ dp[e.v]= p.c + e.w; pq.push(P(e.v, dp[e.v])); }
            }
        }
        return inf;
    };
    int l = 0, r =*max_element(prices.begin(), prices.end());
    // 二分确认最小费用
    while(l <= r){
        int mid = l +(r - l)/2;
        int ret =dijkstra(mid);
        if(ret != inf){ r = mid -1; }
        else{ l = mid +1; }
    }
    // 再求解最小时长
    int ret =dijkstra(l);
    cout << l << " " << ret << "\n";
    return 0;
}

RC-u5 工序优化

分值:30 思路:动态规划

题目可以归纳如下,更好的理解。定义一个 merge 操作:第 i 项可以和第 i-1 项合并,时间合并,工作时间按第 i-1 项为准,但需额外消耗 Ci。合并可以连续,即 [a, b] 的连续区间可以合并,操作次数为 (b - a) 次。这个操作最多 k 次。

如何理解呢?定义把 [a, b] 连续区间进行合并,则 E[a,b] 合并的时间消耗=(∑Pi)*Ta,E[a,b] 合并的代价=cost[a,b]=∑Ci。能理解这个核心的概念后,那个这个 dp 就相对容易解了。

  1. 定义状态 dp[i][j] 为前 i 项,使用 j 次 merge 操作的最小时间/代价。
  2. 转移方程 dp[i+1+s][j+s] = min(dp[i][j] + E[i+1, i+1+s])。
  3. 结果 ans = min(dp[n-1][j])。

时间复杂度为 O(n*k^2)。

#include<bits/stdc++.h>
using namespace std;
const int64_t inf =(int64_t)1e18;
struct W{int t, p, c;W(){}W(int t,int p,int c):t(t),p(p),c(c){}};
struct E{int64_t p = inf;int64_t c =0;
    booloperator<(const E&rhs)const{return p != rhs.p ? p < rhs.p : c < rhs.c;}
    E operator+(const E&rhs)const{return{p+rhs.p, c+rhs.c};}};

int main(){
    int n, k; cin >> n >> k;
    vector<W>tasks(n);
    for(int i = 0; i < n; i++){ W &w = tasks[i]; cin >> w.t >> w.p >> w.c; }
    // 预处理,时间和费用的前缀和
    vector<int64_t>pre_p(n +1,0); vector<int64_t>pre_c(n +1,0);
    for(int i = 0; i < n; i++){ pre_p[i +1]= pre_p[i]+ tasks[i].p; pre_c[i +1]= pre_c[i]+ tasks[i].c; }
    // 定义 dp[i][j], 前i项使用j次操作的最小时间/费用
    vector<vector<E>>dp(n,vector<E>(k +1));
    for(int i = 0; i <= k && i < n; i++){ dp[i][i]={(pre_p[i +1]- pre_p[0])* tasks[0].t, pre_c[i +1]- pre_c[1]}; }
    // 刷表
    for(int i = 0; i < n; i++){
        for(int j = 0; j <= k; j++){
            for(int s = 0; s + j <= k && i + s +1< n; s++){
                E tmp ={(pre_p[i + s +2]- pre_p[i +1])* tasks[i +1].t, pre_c[i + s +2]- pre_c[i +2]};
                E tmp2 = dp[i][j]+ tmp;
                if(tmp2 < dp[i + s +1][j+s]){ dp[i + s +1][j + s]= tmp2; }
            }
        }
    }
    E ans ={inf,0};
    for(int i = 0; i <= k; i++){
        if(dp[n -1][i]< ans){ ans = dp[n -1][i]; }
    }
    cout << ans.p << " " << ans.c << "\n";
    return 0;
}

目录

  1. 前言
  2. 题解
  3. RC-u1 谁拿冠军了?
  4. RC-u2 理包
  5. RC-u3 删除屏蔽词
  6. RC-u4 穷游
  7. RC-u5 工序优化
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Copilot/Codex 中文乱码修复与自动化配置方案
  • Hashcat 使用手册:从入门到高级密码恢复
  • 使用 gpt-oss-20b-WEBUI 快速搭建本地 AI 对话系统
  • 前端表单验证实战:构建健壮的数据入口
  • 鸿蒙 HarmonyOS 6 混合开发:ArkWeb 加载机制与 Cookie 管理
  • 主流 AI 编程模型对比与选型指南
  • 基于机器学习优化生态组合塘污水处理厂脱氮工艺
  • OpenClaw 本地 AI 智能体:从部署到实战指南
  • GitHub Desktop 界面中文本地化完整教程
  • KrLongAI 旗博士:本地部署 AI 数字人口播视频自动化工程
  • WebGIS 实现城市停水影响范围可视化实践
  • 基于 Next.js 构建支持 TokenP 钱包登录的 DApp 前端实战
  • Qwen3.5-9B 如何以 1/13 参数量超越 GPT-oss-120B?架构与性能实测
  • 基于 ESP32-S3 的蓝牙/有线双模智能家居键盘控制器设计详解
  • 单链表综合练习:删除指定值节点、反转链表及查找中间节点
  • Python 自动化办公:使用 xlutils 修改 Excel
  • 国内五大主流大语言模型对比与使用指南
  • C++ 高精度时间库 chrono 详解
  • Claude Code 与 GitHub Copilot CLI 终端选型实测
  • 2017 年技术类书籍精选推荐
  • 相关免费在线工具

    • 加密/解密文本

      使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

    • Gemini 图片去水印

      基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

    • Markdown转HTML

      将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

    • HTML转Markdown

      将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online