一、题目
二、解法
联通三个国家,换一个角度说,就是让三个国家在某一个点集合。
预处理每个点到最近每个国家的距离,可以跑三次
b
f
s
bfs
bfs,把所有的起点塞进去,由于可以无花费走国家,可以写一个双端队列,走国家时插入队首就行了。然后枚举每一个点,让三个点在这个点会面,如果是.
的话需要
−
2
-2
−2,国家的话不需要。
如果两个路径交叉怎么办,没关系,一定有一种方法更优且不交叉。
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define inf 0x3f3f3f3f
const int M = 1005;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,ans,d[4][M][M];char a[M][M];
int dx[4]={1,-1},dy[4]={0,0,1,-1};
struct node
{
int x,y,d;
};
void bfs(int x)
{
deque<node> q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]==x+'0')
{
d[x][i][j]=0;
q.push_back(node{i,j,0});
}
while(!q.empty())
{
node t=q.front();q.pop_front();
for(int i=0;i<4;i++)
{
int tx=t.x+dx[i],ty=t.y+dy[i];
if(tx>=1 && tx<=n && ty>=1 && ty<=m && d[x][tx][ty]==inf)
{
if(a[tx][ty]=='#') continue;
if(a[tx][ty]>='1' && a[tx][ty]<='3')
{
d[x][tx][ty]=t.d;
q.push_front(node{tx,ty,t.d});
}
else
{
d[x][tx][ty]=t.d+1;
q.push_back(node{tx,ty,t.d+1});
}
}
}
}
}
signed main()
{
memset(d,0x3f,sizeof d);
n=read();m=read();
for(int i=1;i<=n;i++)
scanf("%s",a[i]+1);
for(int i=1;i<=3;i++)
bfs(i);
ans=inf;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int tmp=0;
if(a[i][j]=='#') continue;
for(int k=1;k<=3;k++)
{
tmp+=d[k][i][j];
if(d[k][i][j]==inf) break;
}
if(a[i][j]=='.') ans=min(ans,tmp-2);
else ans=min(ans,tmp);
}
if(ans>=inf-2) puts("-1");
else printf("%d\n",ans);
}