题意:

给你一个迷宫,求出从A到B最少需要多少次90度转弯。

思路:

这题和普通迷宫的区别在于:普通迷宫求的是最少走的步数,而这题要我们求的是最少的转弯数,这就导致了dfs的方式对于这题是优于bfs的,因为dfs的状态记录更加方便,而bfs还得专门开数组来记录方向和判重。


既然确定了解法,就可以开干了ヾ(•ω•`)o
首先是读入,没啥好说的,顺带记录一下A和B就行了。这里我采用了雨巨教的一个数记录两个坐标的方法,还是挺方便的,省得用pair。

for(int i=0;i<n;i++) {
        for(int j=0;j<n;j++) {
            int pos = i*1000+j;
            scanf(" %c",&a[pos]);
            if(a[pos]=='A') A=pos;
            else if(a[pos]=='B') B=pos;
        }
}

然后从A开始dfs,我这里使用了三个参数,分别记录(当前位置;当前方向;当前转弯数)。
当我们的操作格遇到B时,我们比较更新答案。当不是B时,我们记录一下在这个分支中,我们来过这个格子,以防出现来回访问的情况。

if(u==B) ans=min(dis,ans);
    if(met[u]) return;
    met[u]=true;

接下来就是走向下一个格子的操作了。
我们使用dx,dy数组操作的方式来确定下一个格子的坐标。
如果下一个格子的方向和现在的不一样,我们就在递归下一层的参数dis上加一。

        if((i==0||i==2)&&dir!=0) {
            if(vis[pos_new]>=dis+1) {
                vis[pos_new]=dis+1;
                dfs(pos_new,0,dis+1);
            }
        }
        else if((i==1||i==3)&&dir!=1) {
            if(vis[pos_new]>=dis+1) {
                vis[pos_new]=dis+1;
                dfs(pos_new,1,dis+1);
            }
        }

如果方向相同,就不加。

        else {
            if(vis[pos_new]>=dis) {
                vis[pos_new]=dis;
                dfs(pos_new,dir,dis);
            }
        }

这里要注意,因为它一开始的方向是任意的,于是我们就把它的方向设置成与横竖都不一样的,导致他开头第一步必转向,然后,再在输出结果的时候减去1就行了。


完整代码:

#include<iostream>
#include<cstring>

using namespace std;
const int N = 1000010;
char a[N];
int ans,A,B,n;
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
int vis[N];
bool met[N];
void dfs(int u,int dir,int dis) {
    if(u==B) ans=min(dis,ans);
    if(met[u]) return;
    met[u]=true;
    for(int i=0;i<4;i++) {
        int x=u/1000+dx[i];
        int y=u%1000+dy[i];
        int pos_new=x*1000+y;

        if(x<0||x>=n||y<0||y>=n) continue;
        if(a[pos_new]=='x') continue;
        if((i==0||i==2)&&dir!=0) {
            if(vis[pos_new]>=dis+1) {
                vis[pos_new]=dis+1;
                dfs(pos_new,0,dis+1);
            }
        }
        else if((i==1||i==3)&&dir!=1) {
            if(vis[pos_new]>=dis+1) {
                vis[pos_new]=dis+1;
                dfs(pos_new,1,dis+1);
            }
        }
        else {
            if(vis[pos_new]>=dis) {
                vis[pos_new]=dis;
                dfs(pos_new,dir,dis);
            }
        }
    }
    met[u]=false;
    return;
}

int main() {
    ans=N;
    memset(vis,0x3f,sizeof vis);
    scanf("%d",&n);
    for(int i=0;i<n;i++) 
        for(int j=0;j<n;j++) {
            int pos = i*1000+j;
            scanf(" %c",&a[pos]);
            if(a[pos]=='A') A=pos;
            else if(a[pos]=='B') B=pos;
        }
    vis[A]=0;  
    dfs(A,3,0);
    if(ans!=N)
        cout<<ans-1;
    else cout<<-1;
    return 0;
}