本体题意不再描述。
把三个国家缩成三个点,那么把这三个点连起来,只有两种方法,可以尝试画一下,然后思路就很明显了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
#define rep1(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define clr(a,x) memset((a),(x),sizeof(a))
const int inf = 1e7;
const int N = 1010;
int n,m;
struct node{
int u,x,y;
node(){}
node(int u=0,int x=0,int y=0):u(u),x(x),y(y){}
};
char ma[N][N];
int dis[3][N][N];
queue<node> Q;
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
int judge(int i,int j){return i>=1&&i<=n&&j>=1&&j<=m;}
int goal;
void relax(int u , int nx,int ny,int add){
if(dis[u][nx][ny]==inf){
dis[u][nx][ny] = add; Q.push(node(u,nx,ny));
}
}
int vis[N][N]={0};
int dist[3][3];
int bfs(int p){
while(!Q.empty()) Q.pop();
rep1(i,1,n) rep1(j,1,m) {
dis[p][i][j]=inf;
if(ma[i][j]-'1' == p) {
Q.push(node(p,i,j));
dis[p][i][j] = 0;
}
}
while(!Q.empty()){
node u =Q.front(); Q.pop();
rep(i,4){
int nx=u.x+dx[i],ny=u.y+dy[i];
if(judge(nx,ny) && ma[nx][ny]=='.'){
relax(p,nx,ny,dis[p][u.x][u.y] + 1);
}
if(judge(nx,ny) && isdigit(ma[nx][ny])){
int to = ma[nx][ny]-'1';
if(dist[p][to] == inf)
dist[p][to] = dis[p][u.x][u.y];
}
}
}
}
int main()
{
rep(i,3) rep(j,3) dist[i][j] = inf;
scanf("%d %d",&n,&m);
rep1(i,1,n) scanf("%s",ma[i]+1);
int ans = inf;
rep(i,3) bfs(i);
ans = dist[0][1]+dist[0][2]+dist[1][2]-max(dist[0][1],max(dist[0][2],dist[1][2]));
rep1(i,1,n) rep1(j,1,m)if(ma[i][j] == '.'){
ans = min(ans , dis[0][i][j]+dis[1][i][j]+dis[2][i][j]-2);
}
printf("%d\n",ans>=inf ? -1 : ans);
return 0;
}