codeforces 591 E. Three States(bfs+思维)

题目链接:http://codeforces.com/contest/591/problem/E

题意:有3个数字表示3个城市,每种城市都是相互连通的,然后不同种的城市不一定联通,'.'表示可以建设道路‘#’表示

不能,问最短建设多少道路能够让3种城市都联通起来

题解:直接bfs一遍所有类型的城市,bfs的同时更新第i类城市到(x,y)点的最短距离,更新第i类城市到第j类城市的距离

具体看一下代码。

#include <iostream>
#include <cstring>
#include <queue>
#define inf 0X3f3f3f3f
using namespace std;
const int M = 1e3 + 10;
char mmp[M][M];
int n , m , dr[4][2] = {1 , 0 , -1 , 0  , 0 , 1 , 0 , -1};
int dis[4][M][M] , de[4][4];//dis表示i种城市到(x,y)点的最短距离初始值为inf,de表示第i个城市到第j个城市的最短距离初始值为inf
struct TnT {
    int x , y;
    TnT(){}
    TnT(int x , int y):x(x) , y(y) {}
};
void bfs(int num) {
    queue<TnT>q;
    for(int i = 0 ; i < n ; i++) {
        for(int j = 0 ; j < m ; j++) {
            if(mmp[i][j] == num + '0') {
                q.push(TnT(i , j));
                dis[num][i][j] = 0;
            }
        }
    }
    while(!q.empty()) {
        TnT gg = q.front();
        q.pop();
        char cp = mmp[gg.x][gg.y];
        if(cp != '.') {
            de[num][cp - '0'] = min(dis[num][gg.x][gg.y] - 1 , de[num][cp - '0']);//更新第num种到其他两种城市的距离
        }
        for(int i = 0 ; i < 4 ; i++) {
            TnT gl = gg;
            gl.x += dr[i][0] , gl.y += dr[i][1];
            if(gl.x >= 0 && gl.x < n && gl.y >= 0 && gl.y < m && mmp[gl.x][gl.y] != '#') {
                if(dis[num][gl.x][gl.y] == inf) {
                    dis[num][gl.x][gl.y] = dis[num][gg.x][gg.y] + 1;//更新第num种城市到(x,y)点的距离,这里直接更新一次就行利用了bfs的特性,好好体会一下。
                    q.push(gl);
                }
            }
        }
    }
}
int main() {
    cin >> n >> m;
    for(int i = 0 ; i < n ; i++) {
        cin >> mmp[i];
    }
    memset(dis , inf , sizeof(dis));
    memset(de , inf , sizeof(de));
    for(int i = 1 ; i <= 3 ; i++) {
        bfs(i);//遍历3种城市
    }
    int ans = de[1][2] + de[1][3];
    ans = min(de[1][2] + de[2][3] , ans);
    ans = min(de[1][3] + de[2][3] , ans);
    for(int i = 0 ; i < n ; i++) {
        for(int j = 0 ; j < m ; j++) {
            if(mmp[i][j] != '.') continue;
            if(dis[1][i][j] == inf || dis[2][i][j] == inf || dis[3][i][j] == inf) continue;
            ans = min(dis[1][i][j] + dis[2][i][j] + dis[3][i][j] - 2 , ans);
        }
    }
    //ans总共的情况就是要么3种城市链接起来要么在中间找一个点算一下到3种城市的距离
    if(ans >= inf) cout << -1 << endl;
    else cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/TnT2333333/p/6872827.html