Algorithm

[백준] 다리 만들기 2146번 (c++)

salmon16 2022. 7. 7. 17:01

출처 : 2146번: 다리 만들기 (acmicpc.net)

 

2146번: 다리 만들기

여러 섬으로 이루어진 나라가 있다. 이 나라의 대통령은 섬을 잇는 다리를 만들겠다는 공약으로 인기몰이를 해 당선될 수 있었다. 하지만 막상 대통령에 취임하자, 다리를 놓는다는 것이 아깝다

www.acmicpc.net

풀이 방법

일단 각각의 섬들을 구분하기 위해 섬에 번호를 붙여 bfs를 통해 land배열에 넣어 주었다.

거리를 구할 때 중복된 경우를 처리하지 않기 위해 섬의 고유 넘버가 작은 쪽에서 큰 쪽으로 가는 경우만 처리했다.

(큰 쪽에서 작은 쪽으로 가는 길과 작은 쪽에서 큰 쪽으로 가는 길이 똑같기 때문)

for문을 통해 맵 전체를 돌며(완전 탐색) s_bfs함수를 통해 bfs를 해주는데 이때 만약 다음 칸이 0이면 len++ 해준 후 

큐에 push 하고 섬의 번호가 자신보다 크면 return len을 통해 거리를 리턴해 준다.

만약 섬의 고유 번호가 자신보다 작거나 같은 경우는 무시해 준다.

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

int N, ans = 987654321;
int land[101][101], temp[101][101], visited[101][101];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};


void bfs(int y, int x, int cnt) {
    queue<pair<int, int>> q;
    q.push(make_pair(y, x));
    visited[y][x] = 1;
    land[y][x] = cnt;
    while(!q.empty()) {
        int yy = q.front().first;
        int xx = q.front().second;
        q.pop();
        for (int i = 0;i < 4;i++) {
            int ny = yy + dy[i];
            int nx = xx + dx[i];
            if (ny >= 0 && ny < N && nx >= 0 && nx < N && visited[ny][nx] == -1 && land[ny][nx] == 1) {
                visited[ny][nx] = 1;
                q.push(make_pair(ny, nx));
                land[ny][nx] = cnt;
            }
        }
    }
}

void make_land() { // 각 섬에 고유 번호 붙이기 
    int cnt = 1;
    memset(visited, -1, sizeof(visited));
    for (int i = 0;i < N;i++) {
        for (int k = 0;k < N;k++) {
            if (visited[i][k] == -1 && land[i][k] != 0) {
                bfs(i, k, cnt);
                cnt++; // 섬 변
            }
        }
    }
}

int s_bfs(int y, int x) {

    memset(visited, -1, sizeof(visited));
    int land_num = land[y][x]; // 섬 번호

    queue<pair<int,pair<int, int>>> q;
    q.push(make_pair(y, make_pair(x, 0))); // y좌표, x 좌표, 거리 
    visited[y][x] = 1;
    while(!q.empty()) {
        int yy = q.front().first;
        int xx = q.front().second.first;
        int len = q.front().second.second;
        q.pop();
        for (int i = 0;i < 4;i++) {
            int ny = yy + dy[i];
            int nx = xx + dx[i];
            if (ny >= 0 && ny < N && nx >= 0 && nx < N && visited[ny][nx] == -1) {
                if (land[ny][nx] == 0) { // 바다인 경우
                    q.push(make_pair(ny, make_pair(nx, len+1)));
                    visited[ny][nx] = 1;
                }
                if (land[ny][nx] > land_num)    return len; // 자신 보다 넘버가 큰 다른 섬을 만난 경우
            }
        }
    }
    return 987654321; // 답이 없는 경우 큰 값 reutrn
}

void solve() {

    for (int i = 0;i < N;i++) {
        for (int k = 0;k < N;k++) {
            if (land[i][k] != 0) {
                ans = min(ans, s_bfs(i, k)); //최소 길이 구하기
            }
        }
    }
}

int main() {
    cin >> N;
    for (int i = 0;i < N;i++) {
        for (int k = 0;k < N;k++) {
            cin >> land[i][k];
        }
    }
    make_land();
    solve();
    cout << ans;
    return 0;
}

'Algorithm' 카테고리의 다른 글

[백준] N-Queen 9663번 (c++)  (0) 2022.07.15
[백준] 플로이드 11404번 (c++)  (0) 2022.07.11
[백준] 빙산 2573번 (c++)  (0) 2022.07.04
[백준] 숨바꼭질 3 (c++)  (0) 2022.06.16
[프로그래머스] 네트워크 (c++)  (0) 2022.05.24