DAY1
杨溢鑫小姐姐出题
好毒瘤啊
T1
低仿机器人
(robo,1s,64M)
题目描述
自从 Dji 推出 robomaster S1 机器人过后,小文就一直缠着爸爸想要一个机器人。没想到爸爸最后竟然带了个低仿 S1--R1 机器人回来。小文哭笑不得,不过低仿就低仿,不玩白不玩,他决定试试这个小机器人的能耐。
小文给这个小机器人布置了 n*m 的场地(场地外用障碍围住),在场地上设置了障碍、水池和靶子。其中,障碍是不可以通过并且无法用水晶弹打掉的,靶子无法通过、但是可以被水晶弹打掉,水池也无法通过、但是水晶弹可以通过水池。
小文检查了一下小机器人,发现它的指令系统很简单。该系统中一共有 6 种指令,指令的使用说明如下:
“FT x” :该指令表示炮台的 90°转动,其中 x∈[0,1],x∈Z,并且 0、1 分别表示逆时针和顺时针。
“FF i” :该指令表示填弹,填弹后弹仓剩余弹量减一,弹夹剩余弹量加一,其中 i∈[0,1]且 i∈Z,i 为 1 表示所填水晶弹为大弹丸,为 0 表示所填水晶弹为小弹丸。
“FE” :该指令表示发射水晶弹,水晶弹的发射方向同炮台的朝向,发射的水晶弹为最后一个填入弹夹的水晶弹,指令执行后弹夹容量减一。
“WT x” :该指令表示机器人的 90°转动, 其中 x∈[0,1],x∈Z, 并且 0、1 分别表示逆时针和顺时针。
“WG y” :该指令表示机器人前进 y 步,其中 y∈[0,max(m,n)),y∈Z。
“END” :该指令将返回“Complete”并停机,不同于编译器先编译后运行,END(及其他将造成停机的情况)后的指令均被无视。
现在小文将要开始测试,但是为了避免自己的指令集让小机器人出现错误,小文给了你场地、小机器人的初始状态和指令集并拜托你帮他计算出小机器人的返回内容、停下的位置、打掉的靶子数量以及小机器人的状态。
注意:
(一)弹夹无弹的情况下将跳过 FE 指令,弹仓无相应弹丸的情况下将跳过 FF 指令;
(二)大水晶弹一发打掉靶子,小水晶弹需两发打掉靶子,靶子打掉后变成空地可通过;
(三)小机器人将在以下情况下返回“ERROR”并停机:
(1)在弹夹已满的情况下继续填弹;
(2)撞上障碍(包括未被打掉的靶子)或者撞进水池;
(3)指令后的参数不满足要求(例:“FE 10”);
(4)无“END”指令;
输入格式
输入文件的第一行为一个正整数 t,表示该题有 t 组数据。
对于每一组数据:
第 1 行为两个正整数 n m
第 2~(n+1)行,每行 m 个正整数,表示地图,其中 1 代表障碍,2 代表靶子,3 代表水池,0 代表空地。
第 n+2 行有 6 个正整数,依次为:机器人横坐标 x 和纵坐标 y,弹夹的容量 a,弹仓内剩余大水晶弹量 b,弹仓内剩余小水晶弹量 c,小文的指令数量 k。(弹夹初始容量默认为 0,炮台和机器人的默认朝向为向上)。
第(n+3)~(n+3+k)行,每行一个指令,指令的正确格式和正确参数见题目描述(数据中无双引号)(不满足要求的参数大小<=10,长度<=3)。
输出格式
输出文件共 t*4 行,其中对于每组数据:
第 1 行输出小机器人的返回内容(“Complete”或“ERROR”,不输出双引号)。
第 2 行输出小机器人停下的位置的横纵坐标(用空格隔开)。
第 3 行输出小机器人打掉的靶子数量 h。
第 4 行依次输出炮台的朝向、机器人的朝向、弹仓剩余大水晶弹量、弹仓剩余小水晶弹量,用空格隔开,其中 0、1、2、3 分别表示上左下右。
若机器人返回“ERROR”后停机,则输出数据为执行错误指令前的数据。(见样例 1)
数据范围
对于 10%的数据,t=1 且输入的指令的参数不会出错。
对于另外 20%的数据,输入的指令的参数不会出错。
对于另外 50%的数据,弹仓只有大弹丸。
对于全部数据,t<=20,n、m<=200,a<=30,b、c<=100,k<=100。
样例输入 1
1
5 5
2 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
4 4 3 1 1 6
WG 4
FT 0
WG 1
FE
END
FF
样例输出 1
ERROR
0 4
0
1 0 1 1
第一眼看上去就是又臭又长的题面...
读完后发现是一个大模拟,就按照他的要求做就好了
“FT x”和”WT x”:这个指令只能进行转动,所以处理起来很轻松,一直记录炮台和机器人本体的方向,然后随着指令转动即可,唯一要检验的就是参数是否符合规则。
“FF i”:这个指令需要讨论一下,以下两种情况该指令不被执行:i==0 且小水晶弹数量为 0、i==1 且大水晶弹数量为 0;注意大弹丸和小弹丸的不同。可以把每一个障碍的生命值设成2,大弹丸使生命值-2,小弹丸使生命值-1
以下两种情况该指令将导致停机并返回”ERROR”:
参数错误、相应水晶弹数量不为 0 且弹夹已满;
其他情况则正常处理,记得记录一下弹丸的大小,发射的时候要用;
“FE”:这个命令不需要检查错误,主要是区分一下发射的是大 or 小水晶弹,前面有靶子的话就相应处理就完事了,没有水晶弹就啥都不干。
“WG y”:这个命令一是注意一下参数不能出错导致”ERROR”,二是注意判断会不会撞到障碍和靶子或者撞进水池导致”ERROR”,都没有问题的话就直接移动到目的点完事。
“END”:看到这个命令直接退出就行。
几个要注意的点:
a.记得记录一下小机器人停机的情况,如果到最后都没有停过机则返回”ERROR”;
b.参数错误有可能是参数的大小不对,也有可能是参数的类型不对如(“FT 0.3”)。建议使用 getline 处理,总之处理参数也不需要多打几行……
c.记得出现过停机情况则之后的所有指令全部无视,所以记得全部读入一下别一不小心直接开始读下一组数据了……
d.大概就这样,总之注意一下题目里的小细节,认真读题就没啥问题了
另外不要用scanf,因为读不了空格之后的东西...亲身体验
还有上一步是指执行指令之前,不是指撞到障碍或者掉水里的上一步...又坑了我一次...
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int xGo[4]={-1,0,1,0}; const int yGo[4]={0,-1,0,1}; int n,m,map[220][220][2]; int x,y,fOri,wOri,maxCilp,totCilp,cilp[32],bigBullet,smallBullet,k,endIf,totTarget; void IN_Map_Robot(); void OutPut(int); int Para(char str[]); void FortCom(char str[]); void WheelCom(char str[]); void EndCom(char str[]); int main() { freopen("robo.in","r",stdin); freopen("robo.out","w",stdout); int t; scanf("%d",&t); while(t--) { IN_Map_Robot(); while(k--) { char str[10]; cin.getline(str,10); if(endIf) continue; if(str[0]=='F') FortCom(str); if(str[0]=='W') WheelCom(str); if(str[0]=='E') EndCom(str); } if(!endIf) OutPut(0); } fclose(stdin); fclose(stdout); return 0; } void IN_Map_Robot() { memset(map,0,sizeof(map)); totCilp=0,fOri=0,wOri=0,endIf=0,totTarget=0; scanf("%d%d",&n,&m); for(int i=0;i<n;++i) for(int j=0;j<m;++j) scanf("%d ",&map[i][j][0]); scanf("%d %d %d %d %d %d ",&x,&y,&maxCilp,&bigBullet,&smallBullet,&k); } void FortCom(char str[]) { if(str[1]=='T') { int par=Para(str+3); if(par==0) fOri=(fOri+1)%4; else if(par==1) fOri=(fOri+3)%4; else { OutPut(0); return ; } } if(str[1]=='F') { int par=Para(str+3); if((par==0&&smallBullet==0)||(par==1&&bigBullet==0)) return; if(par==0&&totCilp<maxCilp) cilp[++totCilp]=par,smallBullet--; else if(par==1&&totCilp<maxCilp) cilp[++totCilp]=par,bigBullet--; else { OutPut(0); return ; } } if(str[1]=='E') { if(totCilp==0) return ; int nx,ny; for(int i=1;;++i) { nx=x+xGo[fOri]*i,ny=y+yGo[fOri]*i; if(nx<0||nx>=n||ny<0||ny>=m) break; if(map[nx][ny][0]==1||map[nx][ny][0]==2) break; } totCilp--; if(nx<0||nx>=n||ny<0||ny>=m) return ; if(map[nx][ny][0]==1) return ; if(cilp[totCilp+1]||map[nx][ny][1]) { map[nx][ny][0]=0; totTarget++; } else map[nx][ny][1]=1; } } void WheelCom(char str[]) { if(str[1]=='T') { int par=Para(str+3); if(par==0) wOri=(wOri+1)%4; else if(par==1) wOri=(wOri+3)%4; else { OutPut(0); return ; } } else { int par=Para(str+3); int nx=x+xGo[wOri]*par,ny=y+yGo[wOri]*par; if(nx<0||nx>=n||ny<0||ny>=m) { OutPut(0); return ; } else { for(int i=1;i<=par;++i) { nx=x+xGo[wOri]*i,ny=y+yGo[wOri]*i; if(map[nx][ny][0]) { OutPut(0); return ; } } } x=nx,y=ny; } } void EndCom(char str[]) { OutPut(1); } void OutPut(int type) { endIf=1; if(type) printf("Complete "); else printf("ERROR "); printf("%d %d ",x,y); printf("%d ",totTarget); printf("%d %d %d %d ",fOri,wOri,bigBullet,smallBullet); } int Para(char str[]) { int i,re=0; for(i=0;;++i) { if(str[i]=='.') return 114514; if(str[i]=='