题目链接:https://atcoder.jp/contests/abc387/tasks/abc387_d
题意:
从S点出发,返回到G点所需的步数。每次移动的方向有限制,如果上次是上下移动,那么这次就必须是左右移动。开始时可以从上下左右四个方向开始移动
思路:
BFS,分情况讨论,即开始是上下移动和开始是左右移动两种不同情况,可以用结构体存储步数和移动朝向(也可以直接在地图上标注移动步数), 注意不能移动到一格两次,以及不能越界或者到有阻挡的位置
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int h,w;
struct node{int x;int y;int step;int op;
};
int dx[]={1,-1,0,0};
int dy[]={0,0,-1,1};const int maxn=1e3+5;
char maze[maxn][maxn];
int bfs(queue<node>q,int stx,int sty,int edx,int edy,int op,bool p[][maxn]);
bool isok(int nx,int ny)
{if(nx>=1&&nx<=h&&ny>=1&&ny<=w&&maze[nx][ny]!='#')return true;return false;
}
signed main()
{ios::sync_with_stdio(false),cin.tie(0);cin>>h>>w;int stx,sty;int edx,edy;for(int i=1;i<=h;i++){for(int j=1;j<=w;j++){cin>>maze[i][j];if(maze[i][j]=='S'){stx=i;sty=j;}if(maze[i][j]=='G'){edx=i;edy=j;}}}bool v[maxn][maxn];bool h[maxn][maxn];memset(v,true,sizeof(v)); memset(h,true,sizeof(h)); queue<node>q1;queue<node>q2; int a=bfs(q1,stx,sty,edx,edy,0,v);int b=bfs(q2,stx,sty,edx,edy,1,h);if(a>0&&b>0)cout<<min(a,b);else cout<<max(a,b);return 0;
}
int bfs(queue<node>q,int stx,int sty,int edx,int edy,int op,bool p[][maxn])
{//op0代表竖着走 q.push(node{stx,sty,0,op});p[stx][sty]=false;while(!q.empty()){node x=q.front();q.pop();if(x.x==edx&&x.y==edy){return x.step;}if(x.op==0){for(int i=0;i<2;i++){int nx=x.x+dx[i];int ny=x.y;if(isok(nx,ny)&&p[nx][ny]){q.push(node{nx,ny,x.step+1,1});p[nx][ny]=false;} }}else if(x.op==1){for(int i=2;i<4;i++){int nx=x.x;int ny=x.y+dy[i];if(isok(nx,ny)&&p[nx][ny]){q.push(node{nx,ny,x.step+1,0});p[nx][ny]=false;}}}}return -1;
}