[BOJ] 2146. 다리 만들기

Feb 20, 2019


https://www.acmicpc.net/problem/2146

BFS를 2번 하여 문제를 풀었습니다.(섬카운트, 다리만들기)

먼저 섬마다 cnt를 줘서 1섬, 2섬, 3섬… 식으로 만든 후,(이또한 BFS)

BFS를 시작하기 전 섬의 끝에서 하기 위해 반복문을 사용했습니다.

반복문안에서 BFS로 들어가면 len배열을 통해 bfs를 해서 다리의 길이를 모두 체크했습니다.

마지막으로 다리 길이가 가장 작은 len을 result로 해줬습니다.

#include <iostream>
#include <queue>
using namespace std;
int map[101][101];
int len[101][101];//다리 카운트
int original[101][101];//ch배열 연산 후 다시 초기화하기 위해
bool tmpch[101][101];//섬마다 cnt하기위해 잠깐 쓰는 ch
queue <pair<int, int>> q;
int dx[] = { -1,0,1,0 };
int dy[] = { 0,-1,0,1 };
int result = 2000000000, n;
void bfs(int r, int c) {//다리길이를 bfs
    q.push(make_pair(r, c));
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx >= 0 && ny >= 0 && nx < n&&ny < n) {
                if (map[nx][ny] != map[r][c]&&map[nx][ny]!=0) {//다른 섬에 도착했을 때
                    result = result < len[x][y]-1 ? result : len[x][y]-1;
                    while (!q.empty()) q.pop();//큐를 모두 비워준다
                    return;
                }
                if (len[nx][ny] == false) {
                    len[nx][ny] = len[x][y]+1;
                    q.push(make_pair(nx, ny));
                }
            }
        }
    }
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    int tmp, cnt = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> tmp;
            map[i][j] = tmp;
            len[i][j] = tmp;
            original[i][j] = tmp;
        }
    }
    for (int i = 0; i < n; i++) {//섬마다 cnt하기위한 bfs
        for (int j = 0; j < n; j++) {
            if (map[i][j] != 0 && tmpch[i][j] == false) {
                cnt++;
                map[i][j] = cnt;
                tmpch[i][j] = true;//tmpch를 true로 줘서 4방향에 true 가 있으면 같은 섬으로 구분 짓기위해
                q.push(make_pair(i, j));
                while (!q.empty()) {
                    int x = q.front().first;
                    int y = q.front().second;
                    q.pop();
                    for (int k = 0; k < 4; k++) {
                        int nx = dx[k] + x;
                        int ny = dy[k] + y;
                        if (nx >= 0 && ny >= 0 && nx < n&&ny < n) {
                            if (map[nx][ny] != 0 && tmpch[nx][ny] == false) {
                                map[nx][ny] = cnt;
                                tmpch[nx][ny] = true;
                                q.push(make_pair(nx, ny));
                            }
                        }
                    }
                }
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {//섬의 끝에서 다리를 짓기 위해 반복문 사용
            if (map[i][j] != 0) {
                for (int k = 0; k < 4; k++) {
                    int nx = dx[k] + i;
                    int ny = dy[k] + j;
                    if (nx >= 0 && ny >= 0 && nx < n&&ny < n) {
                        if (map[nx][ny] == 0) {
                            bfs(i, j);
                            for (int r = 0; r < n; r++) {
                                for (int t = 0; t < n; t++) {
                                    len[r][t] = original[r][t];//ch다시 초기화
                                }
                            }
                            break;
                            //한번만 체크하면되니까 바로 break
                        }
                    }
                }
            }
        }
    }
    cout << result << '\n';
}
  • 혼잣말

예전에 풀어봤던 문제인데도 시간이 좀 걸렸다…(2시간..ㅠ)
오랜만에 제대로 풀어보는 BFS라 좀 까먹었던 것 같다.
덕분에 다시 BFS세포가 생겼다^^
처음에 섬을 카운트하는데 BFS말고 다른 방식을 찾으려다가 도저히 없는 것같아서
BFS를 썻다ㅋㅋㅋㅋㅋ;;;
시간이 많이 걸릴 것 같았는데 36ms밖에 안걸려서 살짝 좋았던ㅎㅎ