cf 591 E.Three States 01bfs

传送门

有3个城市,'.'表示空地,可以用于建桥,'#'是城墙。
然后求至少需要建几个桥才能使得3个城市连通。
思路是用01bfs
建立一个数组dis[k][i][j]表示从第k个城市出发到i,j至少要建筑几个桥。
然后进行3次01bfs,因为'.'需要花费,权值是1,所以放在双端队列的尾部,其他放在双端队列的首部,每次都取双端队列的首部进行bfs
最后遍历每个点,在3个城市都能到达的前提下。
int now = dis[0][i][j] + dis[1][i][j] + dis[2][i][j] - 2 * (s[i][j] == '.');因为'.'算了3次,所以必须要剪掉2次。
就是一种方案,求出最小方案就是答案。

也可以用最短路去求出距离,但最短路的时间复杂度明显高了,对于权值只有0和1的情况下最好用01bfs,时间复杂度低一点

#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
using namespace std;
template<typename T = long long> inline T read() {
    T s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();} 
    return s * f;
}
#ifdef ONLINE_JUDGE
#define qaq(...) ;
#define qwq(c) ;
#else
#define qwq(a, b) for_each(a, b, [=](int x){cerr << x << " ";}), cerr << std::endl
template <typename... T> void qaq(const T &...args) {
    auto &os = std::cerr;
    (void)(int[]){(os << args << " ", 0)...};
    os << std::endl;
}
#endif
const int N = 1e3 + 5, M = 1e6 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f; const ll linf = 0x7f7f7f7f7f7f7f7f;
char s[N][N];
int dis[4][N][N];
struct Node{
    int x, y;
};
int dir[][2] = {1,0, -1,0, 0,1, 0,-1};
void bfs01(int st, int sx, int sy, int n, int m){
    deque<Node> q;
    q.push_back(Node{sx, sy});
    dis[st][sx][sy] = 0;
    while(!q.empty()) {
        Node tmp = q.front(); q.pop_front();
        int x = tmp.x, y = tmp.y;
        for(int i = 0; i < 4; i++) {
            int xx = x + dir[i][0], yy = y + dir[i][1];
            if(xx < 1 || xx > n || yy < 1 || yy > m || s[xx][yy] == '#') continue;
            int nowdis = dis[st][x][y] + (s[xx][yy] == '.');
            if(nowdis < dis[st][xx][yy]) {
                dis[st][xx][yy] = nowdis;
                if(s[xx][yy] == '.') q.push_back(Node{xx, yy});
                else q.push_front(Node{xx, yy});
            }
        }
    }
}
void solve(int kase){
    memset(dis, 0x3f, sizeof(dis));
    int n = read(), m = read(); 
    for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
    for(int k = 1; k <= 3; k++) {
        int x = 0, y = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(s[i][j] == '0' + k) {
                    x = i, y = j;
                }
            }
        }
        bfs01(k - 1, x, y, n, m);
    }
    int ans = -1;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            if(dis[0][i][j] != INF && dis[1][i][j] != INF && dis[2][i][j] != INF) {
                int now = dis[0][i][j] + dis[1][i][j] + dis[2][i][j] - 2 * (s[i][j] == '.');
                if(ans == -1) ans = now;
                else ans = min(ans, now);
            }
        }
    }
    printf("%d\n", ans);
}
const bool ISFILE = 0, DUO = 0;
int main(){
    clock_t start, finish; start = clock();
    if(ISFILE) freopen("/Users/i/Desktop/practice/in.txt", "r", stdin);
    if(DUO) {CASE solve(kase);} else solve(1);
    finish = clock(); 
    qaq("\nTime:", (double)(finish - start) / CLOCKS_PER_SEC * 1000, "ms\n");
    return 0;
}
posted @ 2021-04-26 14:35  Emcikem  阅读(90)  评论(0编辑  收藏  举报