【JZOJ5793】小S练跑步【BFS】
题目大意:
题目链接:https://jzoj.net/senior/#main/show/5793
题目图片:
http://wx1.sinaimg.cn/mw690/0060lm7Tly1fvx7ksrc55j30j20dw3z4.jpg
http://wx3.sinaimg.cn/mw690/0060lm7Tly1fvx7kss9v0j30jb0g1jro.jpg
思路:
P.S.本蒟蒻的语文不好,对于很难简化的题目起不到什么简化所用。各位dalao就看题目图片吧QWQ
正题:
很裸的广搜啊。。。
对于一个点,向四个方向搜,直到遇到不能走的位置在停下。
例如:
就往四个方向枚举,直到四个方向都走到底为止。
那么上图能走的(能转移的)被标记成红色就是:
这也就是和普通广搜的区别吧。。。
- 普通广搜:每次往四个方向搜一个格子。
- 这道题:每次往四个方向搜到不能搜为止。
其实很像最小拐弯问题吧。
还有,这道题的数组也会有一个小变化。当我们搜到一个点的时,不要立刻,因为可能会遇到如下情况:
蓝色的块从绿色的块转移来,已经被标记。
我们现在要从红色点往右搜,那么
当我们搜到时,如果直接退出,不继续往后搜,那么就会导致的本来应该搜到的格子无法搜到。
所以就应该直接跳过已被标记的格子,直接跳到下一个
注意终点也有可能是。但是这种情况还是算可以到达的。记得先将终点的去掉。
代码:
#include <cstdio>
#include <queue>
#include <ctime>
#include <cstring>
#include <iostream>
#define N 510
using namespace std;
const int dx[]={0,1,-1,0,0};
const int dy[]={0,0,0,1,-1};
const char way[]={' ','D','U','R','L'}; //四个方向
int n,m;
char c[N][N];
bool vis[N][N];
void bfs()
{
queue<int> x;
queue<int> y;
queue<int> dis;
vis[1][1]=1;
x.push(1);
y.push(1);
dis.push(-1);
while (x.size())
{
if (c[x.front()][y.front()]!='S')
for (int i=1;i<=4;i++)
{
if (c[x.front()][y.front()]==way[i]) continue;
int k=0;
while (1)
{
k++;
int xx=x.front()+k*dx[i];
int yy=y.front()+k*dy[i];
if (xx<1||yy<1||xx>n||yy>m) break;
if (c[xx][yy]=='S') break;
if (c[xx-dx[i]][yy-dy[i]]==way[i]) break;
if (vis[xx][yy]) continue;
vis[xx][yy]=1;
x.push(xx);
y.push(yy);
dis.push(dis.front()+1);
if (xx==n&&yy==m)
{
printf("%d",dis.front()+1);
return;
}
}
}
x.pop();
y.pop();
dis.pop();
}
printf("No Solution");
return;
}
int main()
{
cin>>n>>m;
if (n==1&&m==1)
{
printf("0");
return 0;
}
for (int i=1;i<=n;i++)
cin>>c[i]+1;
c[n][m]=' ';
bfs();
return 0;
}