[题解]2025RaiCom(睿抗)CAIP省赛(本科) - 点格棋

RaiCom(睿抗)机器人开发者大赛CAIP-编程技能赛(RoboCom世界机器人开发者大赛),所有历史真题均在PTA平台教育超市售卖。

  • 题源:RC-u3-点格棋
  • 题意:给定\(N\times M\)的点阵,初始时所有点间均未连边,A和B轮流地在点阵上执行连边操作,A先手。对于每次连边,若相邻两点先前未连边,则每次操作可在其之间连接水平或竖直边,边长度为1。若有玩家连通了\(1\times 1\)大小的矩形,则添加最后边的玩家+1分,且其下回合继续操作。最终得分高的玩家获胜;若平局则B获胜。现给定\(S\)条格式为当前玩家 起点横坐标 起点纵坐标 终点横坐标 终点纵坐标的游戏日志,需检查日志是否存在问题,有问题的日志为无效日志,跳过即可。日志编号从1开始。输出所有有问题的日志编号(若无则输出-1),最终的获胜者及其分数。
  • 关键词:模拟(签到题)
  • 题解:一道比较考验细节的大模拟。需要注意:
    1. 本回合实际玩家与应为玩家不符(尤其是连局情况)。设置变量cur表示当前回合应为哪个玩家,并在回合结束后根据其是否成环决定是否轮换。
    2. 起点终点不能相同,且不能连斜边。判断曼哈顿距离是否为1即可。(二维平面上两点\((x_1,y_1)\)\((x_2,y_2)\)的曼哈顿距离为\(|x_1-x_2|+|y_1-y_2|\))
    3. 起点和终点不能越界。设置check函数检查是否越界。
    4. 不能重复连边。存储到set里自动去重。
    5. 连边时需建成无向边。正向加边与反向加边。
    6. 一次连边可能形成2个环,分为起终点同行和起终点同列情况,以及起终点谁在上谁在下。对于起终点谁上谁下问题,只需固定一个方向上的点(即在上的)即可。
  • 代码:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using pp=pair<pair<int,int>,pair<int,int>>;
#define int ll
#define endl "\n"
int n,m,s;
bool check(int x,int y) {
    return x>0&&x<=m&&y>0&&y<=n;
}
void solve(){
    cin>>n>>m>>s;
    vector<int>issue;
    set<pp>ss;
    int a=0,b=0;//a和b的得分
    int cur=0;//本回合应为哪个玩家,A先手初始即为A
    for(int i=1;i<=s;i++){
        int p,sx,sy,ex,ey;cin>>p>>sx>>sy>>ex>>ey;
        if(p!=cur){issue.push_back(i);continue;}//本回合实际玩家与应为玩家不符
        if(abs(sx-ex)+abs(sy-ey)!=1){issue.push_back(i);continue;}//曼哈顿距离不为1
        if(!check(sx,sy)||!check(ex,ey)){issue.push_back(i);continue;}//起终点越界
        if(ss.count({{sx,sy},{ex,ey}})){issue.push_back(i);continue;}//重边
        ss.insert({{sx,sy},{ex,ey}}),ss.insert({{ex,ey},{sx,sy}});//建无向边
        int cnt=0;//本回合得分
        if(sx==ex){//同列判环
            int y_min=min(sy,ey);
            if(sx>1&&ss.count({{sx,y_min},{sx-1,y_min}})&&ss.count({{sx-1,y_min},{sx-1,y_min+1}})&&ss.count({{sx,y_min+1},{sx-1,y_min+1}}))cnt++;
            if(sx<m&&ss.count({{sx,y_min},{sx+1,y_min}})&&ss.count({{sx+1,y_min},{sx+1,y_min+1}})&&ss.count({{sx,y_min+1},{sx+1,y_min+1}}))cnt++;
        }
        else if(sy==ey){//同行判环
            int x_min=min(sx,ex);
            if(sy>1&&ss.count({{x_min,sy},{x_min,sy-1}})&&ss.count({{x_min,sy-1},{x_min+1,sy-1}})&&ss.count({{x_min+1,sy},{x_min+1,sy-1}}))cnt++;
            if(sy<n&&ss.count({{x_min,sy},{x_min,sy+1}})&&ss.count({{x_min,sy+1},{x_min+1,sy+1}})&&ss.count({{x_min+1,sy},{x_min+1,sy+1}}))cnt++;
        }
        if(cnt){//得分,下回合玩家不变
            (p==0)?(a+=cnt):(b+=cnt);
            cur=p;
        }else cur=p^1;//未得分,下回合轮换玩家
    }
    if(issue.size()){
        for(int i=0;i<issue.size();i++){
            cout<<issue[i];
            if(i!=issue.size()-1) cout<<' ';//sb PTA,行末空格自己不能吃
        }
        cout<<endl;
    }else cout<<-1<<endl;
    (a>b)?cout<<0<<' '<<a<<endl:cout<<1<<' '<<b<<endl;
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0);
    int t=1;
    while(t--) solve();
    return 0;
}
posted @ 2025-07-17 10:38  椰萝Yerosius  阅读(234)  评论(0)    收藏  举报