因为正在练习图论,所以建图来做吧。
可以假设某个各种的上下左右方向都有一个点,那么这些点的道路里面方向改变的,也就是某个格子上下左右相邻直接的道路的长度是1,其余是0。
那么就可以转化成起点的四个方向点到终点的四个方向点的求解。
那么直接套Dijkstra算法即可。就是建图有那么亿点点麻烦。。。。。。
此外这题使用DFS或者BFS会更简单一些。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 10000+10;
const int maxnn = 100000+10;
int n;
char mp[maxn][maxn];
int mv[4][2] = {
    {-1,0},
    {0,1},
    {1,0},
    {0,-1}
};
int offset[4] = {3,2,1,4};
//链式前向星存图
struct sy{
    int to;
    int next;
    int w;
} edge[maxnn];
int head[maxnn];
struct Node{
    int number;
    int len;
    bool operator < (const Node &n) const
    {
        return len>n.len;
    }
} ;
int cnt = 0;
void add_edge(int x, int y, int w)
{
    edge[++cnt].next = head[x];
    edge[cnt].to = y;
    edge[cnt].w = w;
    head[x] = cnt;
}
bool vis[maxnn];
//起点的编号。
int origin[4];
int ans[maxnn];
//终点的编号
map<int, int> destination;

int min(int a, int b, int c, int d)
{
    int num = INT_MAX;
    if (a<num) num = a;
    if (b<num) num = b;
    if (c<num) num = c;
    if (d<num) num = d;
    return num;
}

int dijkstra(int bg)
{
	memset(vis, 0, sizeof(vis));
    memset(ans, 127, sizeof(ans));
	ans[bg] = 0;
    priority_queue<Node> pq;
    pq.push({bg,0});
    while (pq.size())
    {
        Node nd = pq.top();
        pq.pop();
        int number = nd.number;
        if (vis[number]) continue;
        vis[number] = 1;
        for (int i=head[number];i;i = edge[i].next)
        {
            int next = edge[i].to;
            int w = edge[i].w;
            if (ans[number]+w<ans[next])
            {
                ans[next] = ans[number]+w;
                pq.push({next, ans[next]});
            }
        }
    }
//    for (int i=0;i<4;i++) cout<<"destination="<<destination[i]<<endl; 
    return min(ans[destination[0]],ans[destination[1]],ans[destination[2]],ans[destination[3]]);
}

signed main()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            cin>>mp[i][j];
        }
    }
    int nm[4];
    //建图
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
        	if (mp[i][j]=='x') continue;
            nm[0] = ((i-1)*n+j-1)*4+1;
            nm[1] = ((i-1)*n+j-1)*4+4;
            nm[2] = ((i-1)*n+j-1)*4+3;
            nm[3] = ((i-1)*n+j-1)*4+2;
            int num1 = ((i-1)*n+j-1)*4+1;
            int num2 = num1+1;
            int num3 = num2+1;
            int num4 = num3+1;
            if (mp[i][j]=='A') 
            {
                origin[0] = num1;
                origin[1] = num2;
                origin[2] = num3;
                origin[3] = num4;
            }
            if (mp[i][j]=='B')
            {
                destination[0] = num1;
                destination[1] = num2;
                destination[2] = num3;
                destination[3] = num4;
            }
            add_edge(num1, num2, 1);
            add_edge(num2, num1, 1);
            add_edge(num2, num3, 1);
            add_edge(num3, num2, 1);
            add_edge(num3, num4, 1);
            add_edge(num4, num3, 1);
            add_edge(num4, num1, 1);
            add_edge(num1, num4, 1);
            
            add_edge(num1, num3, 0);
            add_edge(num3, num1, 0);
            
            add_edge(num2, num4, 0);
            add_edge(num4, num2, 0);
            
            for (int k=0;k<4;k++)
            {
                int next_x = i+mv[k][0];
                int next_y = j+mv[k][1];
//                cout<<"next_x="<<next_x<<" "<<"next_y="<<next_y<<endl;
                if (mp[next_x][next_y]==0||mp[next_x][next_y]=='x') continue;
                int num = ((next_x-1)*n+next_y-1)*4+offset[k];
//                cout<<nm[k]<<' '<<num<<endl; 
                add_edge(nm[k], num, 0);
            }
        }
    }
    int as = INT_MAX;
    for (int i=0;i<4;i++)
    {
    	int temp = dijkstra(origin[i]);
//    	cout<<"temp="<<temp<<endl;
        as = min(temp,as);
    }
    if (as>=INT_MAX) {
        cout<<-1<<endl;
        return 0;
    }
    cout<<as<<endl;
    return 0;
}