吐槽下题目:不愧是cf,真的就是阅读理解,抛开复杂的题意,就是一个广搜,不过需要存三种情况.......
题意:现在有三个地盘,然后要修一条可以连通三个城市的道路,并且要最短,可以穿过其他人的地盘来连通
题解:记忆广搜,以每个点来广搜会超时,但是以每个地盘的数字来进行广搜就可以了
先把一个地盘的所有点压入队列,然后来广搜全局,再用数组记录当前到其他剩余点所需要的时间戳,
然后重复两次
最后遍历全图对于每个点来进行三个时间戳求和,取最小,即答案
时间复杂度:图片说明

#include<bits/stdc++.h>
using namespace std;

struct node
{
    int x,y;
}r,f;
queue<node>Q;
int n,m,T[4][1005][1005],dx[]={0,0,1,-1},dy[]={1,-1,0,0};
char R[1005][1005];
void BFS(int a)
{
    int i,j,X,Y;
    for(i=0;i<n;i++)
        for(j=0;j<m;j++)
        {
            T[a][i][j]=1e8;
            if(R[i][j]-'0'==a)T[a][i][j]=0,r.x=i,r.y=j,Q.push(r);
        }
    while(!Q.empty())
    {
        f=Q.front(),Q.pop();
        for(i=0;i<4;i++)
        {
            X=f.x+dx[i],Y=f.y+dy[i],j=T[a][f.x][f.y];
            if(X<0||X>=n||Y<0||Y>=m||R[X][Y]=='#')continue;
            if(R[X][Y]=='.')j++;
            if(j<T[a][X][Y])T[a][X][Y]=j,r.x=X,r.y=Y,Q.push(r);
        }
    }
}
int main()
{
    int i,j,t,ans=1e8;
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++)scanf("%s",R[i]);
    BFS(1),BFS(2),BFS(3);
    for(i=0;i<n;i++)
        for(j=0;j<m;j++)
        {
            if(R[i][j]=='#')continue;
            t=T[1][i][j]+T[2][i][j]+T[3][i][j];
            if(R[i][j]=='.')t-=2;
            ans=min(ans,t);
        }
    if(ans==1e8)ans=-1;
    printf("%d\n",ans);
}