题解:P9966 [THUPC 2024 初赛] 机器人

· · 题解

看大家都是用指针写的,来篇非指针链表的题解。

对于每一个指令,可以看成是一条链,对于不是 REPLACE 或者 TRIGGER 的指令,这条链上只有一个元素,而对于这两个指令,就可以把后续读入的指令接到前一个指令的后面,形成一个链表。

存指令时,只需要记录该指令的链表的头结点即可。

读入

不是 REPLACE 或者 TRIGGER 的指令,直接读入即可。

这两个指令可以递归读入。

基础指令

SLACKOFF 指令

最简单的一个,直接输出即可。

MOVE 指令

判断一下左右手,把当前手指向的人的编号加上 z,然后取模一下 n

SWAP 指令

把两条指令对应的链表的头结点交换一下。

MIRROR 指令

把操作中的 h 异或一下 1 即可。

REPLACE 指令

基础指令中最难的一个。

一个很基础的想法是,直接把后面的指令的起始结点作为需要替换指令的头节点。

但这样会有一个问题,这两个指令同时指向链表中的同一个结点,对于 MIRROR 指令,会一次修改到两个结点。

正确的方法是把后面的指令复制到一个空的结点里,把需要替换的指令改成新复制的指令。

高级指令

ACTIVATE 指令

非常简单,把目标的所有不是 TRIGGER 的指令都跑一遍就行。

TRIGGER 指令

首先,对于每一条执行完的指令,都要检查一下有没有触发改指令。

第一种触发方式,很简单,直接判断一下就行。

对于第二种,可以设置一个变量,看看是不是由 TRIGGER 指令触发的。

需要注意 ACTIVATE 指令中所执行的指令并不能触发 TRIGGER 指令。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define endl '\n'
#define fi first
#define se second
#define pii pair<int,int>
#define p_q priority_queue
#define iter iterator
#define pb push_back
#define eps 1e-8
#define oper operator
#define mk make_pair
#define ls x<<1
#define rs x<<1|1
int n,m,k,tot=0;
struct node{
    int s,s1;
    int h,x,y,nxt,z;
}a[1000005];
struct robot{
    int l,r;
    int head[15];
}r[105];
map<string,int>mp;
int readin(){
    tot++;
    int x=tot;
    string s;
    cin>>s;
    a[tot].s=mp[s];
    if(s=="MOVE"){
        cin>>a[tot].h>>a[tot].z;
    }
    else if(s=="SWAP"){
        cin>>a[tot].h>>a[tot].x>>a[tot].y;
    }
    else if(s=="MIRROR"){
        cin>>a[tot].h>>a[tot].x;
    }
    else if(s=="REPLACE"){
        cin>>a[tot].h>>a[tot].x;
        a[tot].nxt=readin();
    }
    else if(s=="ACTIVATE"){
        cin>>a[tot].h;
    }
    else if(s=="TRIGGER"){
        string ss,t="";
        cin>>ss;
        for(int i=0;i<ss.size()-1;i++){
            t+=ss[i];
        }
        a[tot].s1=mp[t];
        a[tot].nxt=readin();
    }
    return x;
}
void Do(int x,int y,bool is_trigger);
void checktrigger(int x,int y,bool is_trigger){
    int X=r[x].r;
    if(x==X) return ;
    for(int i=1;i<=m;i++){
        int Y=r[X].head[i];
        if(a[Y].s==7){
            bool F=0;
            if(a[Y].s1==7){
                if(is_trigger) F=1;
            }else{
                if(a[Y].s1==a[y].s) F=1;
            }
            if(F){
                Do(X,a[Y].nxt,1);
                return ;
            }
        }
    }
}
void Do(int x,int y,bool is_trigger){
    if(k==0) exit(0);
    k--;
    if(a[y].s==1){
        printf("Robot %d slacks off.\n",x);
    }else if(a[y].s==2){
        printf("Robot %d moves its ",x);
        if(a[y].h==0) cout<<"left hand towards Robot ";
        else cout<<"right hand towards Robot ";
        if(a[y].h==0){
            r[x].l=(r[x].l+a[y].z)%n;
            cout<<r[x].l;
        }
        else{
            r[x].r=(r[x].r+a[y].z)%n;
            cout<<r[x].r;
        }
        cout<<".\n";
    }
    else if(a[y].s==3){
        int X=r[x].l;
        if(a[y].h==1) X=r[x].r;
        printf("Robot %d swaps a line of command with Robot %d.\n",x,X);
        swap(r[x].head[a[y].y],r[X].head[a[y].x]);
    }else if(a[y].s==4){
        int X=r[x].l;
        if(a[y].h==1) X=r[x].r;
        printf("Robot %d modifies a line of command of Robot %d.\n",x,X);
        int Y=r[X].head[a[y].x];
        if(a[Y].s!=1&&a[Y].s!=7){
            a[Y].h^=1;
        }else if(a[Y].s==7){
            Y=a[Y].nxt;
            if(a[Y].s!=1){
                a[Y].h^=1;
            }
        }
    }else if(a[y].s==5){
        int X=r[x].l;
        if(a[y].h==1) X=r[x].r;
        printf("Robot %d replaces a line of command of Robot %d.\n",x,X);
        tot++;
        r[X].head[a[y].x]=tot;
        a[tot]=a[a[y].nxt];
        int Y=a[y].nxt;
        if(a[Y].s==7){
            tot++;
            a[tot-1].nxt=tot;
            a[tot]=a[a[Y].nxt];
        }
    }else if(a[y].s==6){
        int X=r[x].l;
        if(a[y].h==1) X=r[x].r;
        printf("Robot %d activates Robot %d.\n",x,X);
        for(int i=1;i<=m;i++){
            if(a[r[X].head[i]].s!=7) Do(X,r[X].head[i],0);
        }
    }
    if(!k) exit(0);
    checktrigger(x,y,is_trigger);
}
int main(){
//  freopen("5.in","r",stdin);
//  freopen("5.out","w",stdout);
    mp["SLACKOFF"]=1;
    mp["MOVE"]=2;
    mp["SWAP"]=3;
    mp["MIRROR"]=4;
    mp["REPLACE"]=5;
    mp["ACTIVATE"]=6;
    mp["TRIGGER"]=7;
    cin>>n>>m>>k;
    for(int i=1;i<=500000;i++){
        a[i].h=0;
        a[i].nxt=0;
        a[i].s=0;
        a[i].s1=0;
        a[i].x=0;
        a[i].y=0;
        a[i].z=0;
    }
    for(int i=0;i<n;i++){
        cin>>r[i].l>>r[i].r;
        for(int j=1;j<=m;j++){
            r[i].head[j]=readin();
        }
    }
    while(1){
        for(int i=0;i<n;i++){
            for(int j=1;j<=m;j++){
                if(a[r[i].head[j]].s!=7) Do(i,r[i].head[j],0);
            }
        }
    }
    return 0;
}