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