题目
思路
这题的主要难点在于我们不知道是三个起点分别在哪里
但是我们知道三条路径一定会交于某一个点
基于此,我们考虑枚举这一个点,
那么算法的复杂度就卡在这个点和三个王国的国土的最短路径上面
这个可以用bfs来预处理,\(dis[k][i][j]\)第k个王国距离点\((i,j)\)的最短距离
我们只需要考虑经过的是国土还是公有土地即可
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define x first
#define y second
struct node
{
pair<int,int> x;
long long step;
};
int n,m;
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};
char a[1005][1005];
long long dis[4][1005][1005],ans=(1<<30);
deque<node> q;
bool inside(int x,int y)
{
if(1<=x&&x<=n&&1<=y&&y<=m)
return 1;
return 0;
}
void bfs(int col)
{
while(!q.empty())
q.pop_front();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]=='0'+col)
{
dis[col][i][j]=0;
q.push_back((node){make_pair(i,j),0});
}
while(!q.empty())
{
node t=q.front();
q.pop_front();
t.step=dis[col][t.x.x][t.x.y];
for(int i=1;i<=4;i++)
{
int tx=t.x.x+dx[i];
int ty=t.x.y+dy[i];
if(inside(tx,ty)&&a[tx][ty]!='#')
{
int cost=0;
if(a[tx][ty]=='.')
cost++;
if(t.step+cost<dis[col][tx][ty])
{
dis[col][tx][ty]=t.step+cost;
if(cost)
q.push_back((node){make_pair(tx,ty),t.step+cost});
else
q.push_front((node){make_pair(tx,ty),t.step+cost});
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int k=1;k<=3;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dis[k][i][j]=(1ll<<30);
for(int i=1;i<=3;i++)
bfs(i);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]=='#')
continue;
long long val=0;
for(int k=1;k<=3;k++)
val+=dis[k][i][j];
if(a[i][j]=='.')
ans=min(ans,val-2);
else
ans=min(ans,val);
}
}
if(ans>(1ll<<25))
cout<<"-1";
else
cout<<ans;
return 0;
}