因为正在练习图论,所以建图来做吧。
可以假设某个各种的上下左右方向都有一个点,那么这些点的道路里面方向改变的,也就是某个格子上下左右相邻直接的道路的长度是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;
}

京公网安备 11010502036488号