codeforces 590C(bfs)

本体题意不再描述。

把三个国家缩成三个点,那么把这三个点连起来,只有两种方法,可以尝试画一下,然后思路就很明显了。

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值