1 条题解
-
0
自动搬运
来自洛谷,原作者为

Lazy_Labs
如果你仍思念的话 就回来吧搬运于
2025-08-24 22:53:27,当前版本为作者最后更新于2023-12-20 18:40:18,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
-1.HACK
HACK1
输入 1:
2 2 7 1 1 REPLACE 0 1 MOVE 0 1 MIRROR 0 1 0 0 SLACKOFF REPLACE 0 2 SLACKOFF输出 1:(着重看最后一行的
left)Robot 0 replaces a line of command of Robot 1. Robot 0 modifies a line of command of Robot 1. Robot 1 moves its right hand towards Robot 1. Robot 1 replaces a line of command of Robot 0. Robot 0 replaces a line of command of Robot 1. Robot 0 slacks off. Robot 1 moves its left hand towards Robot 1.错于此,转到 坑点1。
HACK2
输入 2:
2 2 4 1 1 MOVE 0 1 ACTIVATE 0 0 0 SLACKOFF SLACKOFF输出 2:(着重看最后一行)
Robot 0 moves its left hand towards Robot 0. Robot 0 activates Robot 0. Robot 0 moves its left hand towards Robot 1. Robot 0 activates Robot 1.错于此,转到 坑点2。
HACK3
3 3 11 2 2 SWAP 0 2 2 SWAP 1 2 2 SWAP 1 2 1 1 2 MIRROR 0 2 REPLACE 1 2 SLACKOFF SLACKOFF 0 2 SLACKOFF ACTIVATE 1 MIRROR 0 3问题在于原代码中,
Replace的update函数中,当恰好更改到当前的指令时,hrbt会变化,与 坑点2 的错误一致。修改方法同 坑点2,提前记录下
hrbt即可。(还是
Replace操作修改到自身的概率太低了,导致我都退役了才被叉)0.前言
你说得对,但是这篇题解很蠢,可能对继承的理解也不是很深,有更简单的写法可以提出来,shaber 作者学习一下。
1.继承
定义一个
struct Command表示一个指令的基类。可以共用同名函数(需要用虚函数即virtual),以及同名变量。代码如下(变量解释见注释):
struct Command { int id;//表示指令的类型,实际上也可以不计这个,直接使用typeid或者其他来实现,id 按照题目指令依次为 1~6。 bool h,tri;//h:这条指令的 h,tri:这条指令是否是trigger触发的 inline virtual void init()=0;//这条指令的初始化 inline virtual void update(int rbt,int cid)=0;//执行这条指令 };下面以 SLACKOFF 来举个例子:
struct Slackoff:Command //:后接继承的函数 { inline void update(int rbt,int cid)override//表示 Command 的虚函数 { printf("Robot %d slacks off.\n",rbt);if(!--k)exit(0);//输出 if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this);//检查右手的 trigger 条件 } inline void init()override{id=0;tri=0;}//tri=0 不为 trigger 指令,id 为 0 };一些实现:
dynamic_cast<Trigger*>cmd可以强制转化
cmd为Trigger类,此时就可以调用Trigger专属的函数。2.指令类
刚刚介绍过了。
3.机器人类
需要存储这个机器人的所有指令,此时可以直接使用
Command* cmd[10];来描述这个机器人的指令。注意,基类不能直接使用
Command定义,定义时一定要用像Slackoff这样的类定义。此时继承的方便性就呈现出来了,当你要依次激活这个机器人的指令的时候,只需要:
for(int i=0;i<m;i++)cmd[i]->update(...);//内部填的啥待会再说就行了。
具体的,机器人类目前要存储:
-
int rbt;表示当前机器人的编号; -
int hd[2];表示机器人的左右手指向; -
Command* cmd[10];表示机器人的所有指令。
4.基础指令
代码最后会统一给出。
4.1 SLACKOFF 和 MOVE
对于所有指令来说,我们知道它们属于某个固定的机器人,于是在执行
update时要传入rbt表示这个指令是由哪个机器人执行的。SLACKOFF 刚刚介绍过了,不再阐述。
MOVE 指令要新存一个变量
z,表示和题目相同。Move内实现的init便需要读入h和z。对于 Move 的
update,我们要找到这个机器人的h手,即Rbt[rbt].hd[h](为了方便,我们将其定义为hrbt),然后将其循环移位即可。注意输出要在移位后执行。4.2 SWAP,MIRROR,REPLACE
这三个指令是对机器人内部的指令进行修改,具体实现如下:
SWAP
十分简单,直接交换两个机器人的
Command指针即可。REPLACE
发现这个指令内部要记一个指令指针
Command* comd,表示这个指令替换时替换成的指令,update也很好实现:只要把目标位置上的指令指针指向comd即可。坑点3
同坑点2,具体的在 HACK3 中叙述过了。
只是作者代码写的太烂了,估计不算什么坑点。
MIRROR
也很简单,只要把目标指令的
h值异或一下即可。吗?
坑点1
考虑一组 hack:
2 2 7 1 1 REPLACE 0 1 MOVE 0 1 MIRROR 0 1 0 0 SLACKOFF REPLACE 0 2 SLACKOFF按照我们的想法,最后一句输出:
Robot 1 moves its right hand towards Robot 1.,实际上应该是left hand。我们发现一件事:当 MIRROR 指令反转的是 REPLACE 过后的指令时,此时直接更改了 REPLACE 指令内部的
comd。然而我们只想要反转真实的指令:此时就要在机器人类中记一个
h[10]表示每个指令的“反转标记”,那么,对于所有update函数来说,我们就要传入一个cid表示当前指令是rbt的第几条指令,然后使用Rbt[rbt].hd[Rbt[rbt].h[cid]^h]来表示当前指令的手。PS:其实可以把指令中的
h和机器人类中的h合并的,但是我懒,于是就直接改了。再次考虑有无其他可能更改
comd的指令,发现没有,那么考虑适配:SWAP:要多交换两条指令的
h数组中的数字。REPLACE:要将当前指令的
h数组置为 0。MIRROR:只要将指向指令的
h数组取反即可。于是,我们便完成了基础指令。
5.高级指令
和普通指令没有区别,也是继承基类
Command。5.1 ACTIVATE
update中直接执行for(int i=0;i<m;i++)Rbt[hrbt].cmd[i]->update(hrbt,i);即可。吗?
坑点 2
你发现一件事,执行每条指令的
update时,当前机器人的手可能会动,所以不能直接用hrbt,而是要在for前将指向的机器人存下来。5.2 TRIGGER
TRIGGER 指令要存储的信息有:
type表示检测的条件,comd表示执行的指令。读题,发现 TRIGGER 指令是在每次指令操作结束后都有可能执行,于是对于机器人类定义一个函数,表示查找是否会执行 TRIGGER 指令。代码如下:
inline void check_trigger(Command* comd) { for(int i=0;i<m;i++)if(cmd[i]->id==6) if(dynamic_cast<Trigger*>(cmd[i])->type==6) { if(comd->tri)return dynamic_cast<Trigger*>(cmd[i])->work(rbt,i); } else if(dynamic_cast<Trigger*>(cmd[i])->type==comd->id) return dynamic_cast<Trigger*>(cmd[i])->work(rbt,i); }注意到题目中的:其他机器人,所以我们要在所有的
update后执行:if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this);其中
dynamic_cast<Trigger*>为强转为Trigger类,且id比较也可以用typeid来解决。介于
TRIGGER并没有实际执行,所以其update为空,新开一个work函数,作为执行TRIGGER时调用的函数。代码:inline void work(int rbt,int cid){comd->update(rbt,cid);}至此,我们完成了所有指令。
6.读入指令
定义一个函数
create表示读入一个指令并且返回一个Command*。代码容易实现(可能有更好的实现,你说的对,但是):
inline Command* create() { string s;cin>>s;Command *comd; if(s=="SLACKOFF")comd=new Slackoff; else if(s=="MOVE")comd=new Move; else if(s=="SWAP")comd=new Swap; else if(s=="MIRROR")comd=new Mirror; else if(s=="REPLACE")comd=new Replace; else if(s=="ACTIVATE")comd=new Activate; else if(s=="TRIGGER")comd=new Trigger; comd->init(); return comd; }我们来考虑实现每个指令的
init。6.1 SLACKOFF,SWAP,MIRROR,ACTIVATE
这四种指令的
init是容易的,直接读入并将id和tri赋值即可。6.2 REPLACE
comd=create()就能完成,剩余部分同上。6.3 TRIGGER
最前面的 COMMANDNAME 确定
type,剩余部分同上。至此,所有部分都完成了。
7.完整代码
#include<bits/stdc++.h> using namespace std; inline int read() { int x(0),f(1);char c=getchar(); while(c<'0'||c>'9')f=c=='-'?-1:1,c=getchar(); while(c<='9'&&c>='0')x=x*10+c-48,c=getchar(); return x*f; } #define hrbt Rbt[rbt].hd[h^Rbt[rbt].h[cid]] int n,m,k; struct Command { int id;bool h,tri; inline virtual void init()=0; inline virtual void update(int rbt,int cid)=0; }; inline Command* create(); struct Trigger:Command { int type;Command* comd; inline void init()override { string s;cin>>s; if(s=="SLACKOFF:")type=0; else if(s=="MOVE:")type=1; else if(s=="SWAP:")type=2; else if(s=="MIRROR:")type=3; else if(s=="REPLACE:")type=4; else if(s=="ACTIVATE:")type=5; else if(s=="TRIGGER:")type=6; comd=create(); id=6;tri=0;comd->tri=1; } inline void update(int rbt,int cid)override{};inline void work(int rbt,int cid){comd->update(rbt,cid);} }; struct Robot { int hd[2],rbt;Command* cmd[10];bool h[10]; inline void check_trigger(Command* comd) { for(int i=0;i<m;i++)if(cmd[i]->id==6) if(dynamic_cast<Trigger*>(cmd[i])->type==6) { if(comd->tri)return dynamic_cast<Trigger*>(cmd[i])->work(rbt,i); } else if(dynamic_cast<Trigger*>(cmd[i])->type==comd->id) return dynamic_cast<Trigger*>(cmd[i])->work(rbt,i); } }Rbt[110]; struct Slackoff:Command { inline void update(int rbt,int cid)override{printf("Robot %d slacks off.\n",rbt);if(!--k)exit(0); if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this);} inline void init()override{id=0;tri=0;} }; inline void move(int &x,int y){x=(x+y)%n;} struct Move:Command { int z; inline void init()override{h=read();z=read();id=1;tri=0;} inline void update(int rbt,int cid)override { move(hrbt,z); printf("Robot %d moves its %s hand towards Robot %d.\n",rbt,h^Rbt[rbt].h[cid]?"right":"left",hrbt);if(!--k)exit(0); if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this); } }; template<typename T> inline void swaps(T &a,T &b,bool &ta,bool &tb){swap(a,b);swap(ta,tb);} struct Swap:Command { int x,y; inline void init()override{h=read();x=read()-1;y=read()-1;id=2;tri=0;} inline void update(int rbt,int cid)override { printf("Robot %d swaps a line of command with Robot %d.\n",rbt,hrbt);if(!--k)exit(0); swaps(Rbt[rbt].cmd[y],Rbt[hrbt].cmd[x],Rbt[rbt].h[y],Rbt[hrbt].h[x]); if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this); } }; struct Mirror:Command { int x; inline void init()override{h=read();x=read()-1;id=3;tri=0;} inline void update(int rbt,int cid)override { printf("Robot %d modifies a line of command of Robot %d.\n",rbt,hrbt);if(!--k)exit(0); Rbt[hrbt].h[x]^=1; if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this); } }; struct Replace:Command { int x;Command* comd; inline void init()override { h=read();x=read()-1; comd=create(); id=4;tri=0; } inline void update(int rbt,int cid)override { printf("Robot %d replaces a line of command of Robot %d.\n",rbt,hrbt);if(!--k)exit(0); // Rbt[hrbt].h[x]=0;Rbt[hrbt].cmd[x]=comd; 感谢 codingwen 发现此行的错误 int qwq=hrbt;Rbt[qwq].h[x]=0;Rbt[qwq].cmd[x]=comd; if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this); } }; struct Activate:Command { inline void init()override{h=read();id=5;tri=0;} inline void update(int rbt,int cid)override { printf("Robot %d activates Robot %d.\n",rbt,hrbt);if(!--k)exit(0); int qwq=hrbt;for(int i=0;i<m;i++)Rbt[qwq].cmd[i]->update(qwq,i); if(Rbt[rbt].hd[1]!=rbt)Rbt[Rbt[rbt].hd[1]].check_trigger(this); } }; inline Command* create() { string s;cin>>s;Command *comd; if(s=="SLACKOFF")comd=new Slackoff; else if(s=="MOVE")comd=new Move; else if(s=="SWAP")comd=new Swap; else if(s=="MIRROR")comd=new Mirror; else if(s=="REPLACE")comd=new Replace; else if(s=="ACTIVATE")comd=new Activate; else if(s=="TRIGGER")comd=new Trigger; comd->init(); return comd; } int main() { n=read(),m=read(),k=read(); for(int i=0;i<n;i++) { Rbt[i].hd[0]=read(),Rbt[i].hd[1]=read();Rbt[i].rbt=i; for(int j=0;j<m;j++)Rbt[i].cmd[j]=create(); } for(int i=0;;(i=i+1)%=n)for(int j=0;j<m;j++)Rbt[i].cmd[j]->update(i,j); return 0; } -
- 1
信息
- ID
- 9583
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者