专题一搜索 E - Crazy Robot
- 题目
There is a grid, consisting of nn rows and mm columns. Each cell of the grid is either free or blocked. One of the free cells contains a lab. All the cells beyond the borders of the grid are also blocked.
A crazy robot has escaped from this lab. It is currently in some free cell of the grid. You can send one of the following commands to the robot: "move right", "move down", "move left" or "move up". Each command means moving to a neighbouring cell in the corresponding direction.
However, as the robot is crazy, it will do anything except following the command. Upon receiving a command, it will choose a direction such that it differs from the one in command and the cell in that direction is not blocked. If there is such a direction, then it will move to a neighbouring cell in that direction. Otherwise, it will do nothing.
We want to get the robot to the lab to get it fixed. For each free cell, determine if the robot can be forced to reach the lab starting in this cell. That is, after each step of the robot a command can be sent to a robot such that no matter what different directions the robot chooses, it will end up in a lab.
InputThe first line contains a single integer tt (1 \le t \le 10001≤t≤1000) — the number of testcases.
The first line of each testcase contains two integers nn and mm (1 \le n, m \le 10^61≤n,m≤106; n \cdot m \le 10^6n⋅m≤106) — the number of rows and the number of columns in the grid.
The ii-th of the next nn lines provides a description of the ii-th row of the grid. It consists of mm elements of one of three types:
- '.' — the cell is free;
- '#' — the cell is blocked;
- 'L' — the cell contains a lab.
The grid contains exactly one lab. The sum of n \cdot mn⋅m over all testcases doesn't exceed 10^6106.
OutputFor each testcase find the free cells that the robot can be forced to reach the lab from. Given the grid, replace the free cells (marked with a dot) with a plus sign ('+') for the cells that the robot can be forced to reach the lab from. Print the resulting grid.
ExampleInput4 3 3 ... .L. ... 4 5 #.... ..##L ...#. ..... 1 1 L 1 9 ....L..#.
Output... .L. ... #++++ ..##L ...#+ ...++ L ++++L++#.
In the first testcase there is no free cell that the robot can be forced to reach the lab from. Consider a corner cell. Given any direction, it will move to a neighbouring border grid that's not a corner. Now consider a non-corner free cell. No matter what direction you send to the robot, it can choose a different direction such that it ends up in a corner.
In the last testcase, you can keep sending the command that is opposite to the direction to the lab and the robot will have no choice other than move towards the lab.
- 思路
嗷卵犟机器人
先考虑实验室周围四个点中空点,显然如果这些点四周的路,除了通向实验室的那条路只有一条路可以走,那么机器人在这个点时,只要给它发送唯一一条路方向的指令,它就只能往实验室走,用+号标记符合这些条件的点;
再沿着+号点周围四个点检查,同样寻找其中除了+号方向、实验室方向以外只有一条路的点,发送指令可以让它被迫走向+号点,对于之后每个点都可以这样做,直到找到所有可行点。
代码我甚至没用bfs或者dfs的一般写法,不过个人感觉更像除了根节点其他节点只有一个子节点的dfs
另外关于数据存储:
开1e6*1e6的二维数组,在自己电脑上都开不出(底层代码限制),更不要说爆评测机内存,不过之前有个同学已经来问过我处理方法了,我当时告诉他的做法是用下标为x*m+y的元素储存点(x,y)的数据,但后来自己提交的时候发现会RE。最后发现是这个原因:当n很小,m很大,比如1*1000000的时候,检查(0,0)点,搜索的时候会搜到(-1,0)去,对应的下标是-1000000,会发生非常严重的数组越界。最后我的处理方式是左上角的点定义为(1,1),下标从m+1开始存储,留足缓冲空间。我队友的处理方式是直接用vector存储,但那玩意我现在还不是特别熟,之后再试试。 - 代码
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; struct node{ int x,y; }; struct node mov[4]={{-1,0},{0,1},{1,0},{0,-1}}; char map[2000005]; bool vis[2000005]; int t,n,m; int lx,ly,tx,ty,nx,ny,ax,ay;//实验室坐标,临时存的坐标,下一个方格的坐标,当前坐标 int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); getchar(); for(int i=1;i<=n;i++){//这把总不至于还来数组越界 for(int j=1;j<=m;j++){ scanf("%1c",&map[i*m+j]); if(map[i*m+j]=='#'){ vis[i*m+j]=1;//方便后续处理 } else if(map[i*m+j]=='L'){ vis[i*m+j]=1; lx=i;ly=j; } else{ vis[i*m+j]=0; } } getchar(); } for(int i=0;i<=m;i++) { vis[i]=1; } for(int i=0;i<=3;i++){ ax=lx+mov[i].x; ay=ly+mov[i].y; if((ax>=1&&ax<=n&&ay>=1&&ay<=m)&&vis[ax*m+ay]==0){ int num=1;//除了实验室、障碍和+号地方还剩的方向,1是为了进循环 while(num==1)//只剩一条路,那么发送这个方向的命令,机器人就会走向实验室 { num=0; for(int i=0;i<=3;i++) { tx=ax+mov[i].x; ty=ay+mov[i].y; if((tx>=1&&tx<=n&&ty>=1&&ty<=m)&&vis[tx*m+ty]==0) { nx=tx;ny=ty; num++; } } if(num==1) { vis[ax*m+ay]=1; ax=nx;ay=ny; } else if(num==0) { vis[ax*m+ay]=1; } } } } //printf("\n"); //printf("\n"); for(int i=m+1;i<=(n+1)*m;i++) { if(map[i]=='#'||map[i]=='L') { printf("%c",map[i]); } else if(vis[i]==1) { printf("+"); } else { printf("."); } if(i%m==0) { printf("\n"); } } // printf("\n"); // printf("\n"); // for(int i=0;i<n*m;i++) // { // printf("%c",map[i]); // if(i%m==(m-1)) // { // printf("\n"); // } // } // printf("\n"); // printf("\n"); // for(int i=0;i<n*m;i++) // { // printf("%d",vis[i]); // if(i%m==(m-1)) // { // printf("\n"); // } // } } return 0; }