BOJ 2146 다리만들기

25947 단어 BFS알고리즘BFS

BOJ 2146 다리만들기 문제이다.

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

int dist[101][101];
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
bool vis[101][101];
int graph[101][101];
int n;
int islandNum = 0;

int main() {
    cout.sync_with_stdio(0);
    cin.tie(0);

    cin >> n;
    for(int  i = 0; i < n; i++) {
        fill(dist[i], dist[i] + n, -1);
    }
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            cin >> graph[i][j];
        }
    }
    queue<pair<int, int>> Q1;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++){
            if(!vis[i][j] && graph[i][j] == 1) {
                islandNum++;
                Q1.push({i, j});
                vis[i][j] = true; graph[i][j] = islandNum;
                while(!Q1.empty()){
                    auto cur = Q1.front(); Q1.pop();
                    for(int i = 0; i < n; i++){
                        int nx = cur.first + dx[i];
                        int ny = cur.second + dy[i];
                        if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
                        if(vis[nx][ny]) continue;
                        if(graph[nx][ny] == 0) continue;
                        Q1.push({nx, ny});
                        vis[nx][ny] = true;
                        graph[nx][ny] = islandNum;
                    }
                }

            }
        }
    }

    queue<pair<int, int>> Q2;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++){
            if(graph[i][j] >= 1) {
                for(int k = 0; k < 4; k++) {
                    int nx = i + dx[k];
                    int ny = j + dy[k];
                    if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
                    if(graph[nx][ny] == 0) {
                        dist[i][j] = 0;
                        Q2.push({i, j});
                        break;
                    }
                }
            }
        }
    }

    int ans = 9999;
    while(!Q2.empty()) {
        auto cur = Q2.front(); Q2.pop();
        for(int i = 0; i < 4; i++) {
            int nx = cur.first + dx[i];
            int ny = cur.second + dy[i];
            if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
            if(graph[cur.first][cur.second] == graph[nx][ny]) continue;
            if(graph[nx][ny] != graph[cur.first][cur.second] && graph[nx][ny] != 0) {
                int cost = dist[nx][ny] + dist[cur.first][cur.second];
                ans = min(cost, ans);
            }
            if(dist[nx][ny] >= 0) continue;
            Q2.push({nx, ny});
            dist[nx][ny] = dist[cur.first][cur.second] + 1;
            graph[nx][ny] = graph[cur.first][cur.second];
        }
    }
    cout << ans;

    return 0;
}

BFS 시에 큐에 넣어지고 빼는 과정에서 내생각과는 다를 수 있으므로 최대, 최소값을 출력하는 과정에서는 되도록이면 BFS과정을 끝낸 후 출력하도록 하자.
각 섬마다 번호를 매겨주고, 주위에 강이 있는 섬의 좌표를 큐에 넣어주고, 간척 일수를 기록할 dist 배열의 값을 0으로 고쳐준다음 에 넣어준 다음 BFS 탐색을 통해 간척하듯이 섬의 범위를 늘려간다. BFS과정에서 다른 섬을 만날경우 지금까지의 거리(dist) 값을 더해주면 해결할 수 있다.


좋은 웹페이지 즐겨찾기