개발자 김수진

[백준] 2146번. 다리 만들기 본문

알고리즘/백준

[백준] 2146번. 다리 만들기

김수진장 2020. 12. 30. 12:28

[문제]

 

www.acmicpc.net/problem/2146

 

2146번: 다리 만들기

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

www.acmicpc.net

[풀이]

 

섬을 연결하는 다리를 설치할 수 있는데, 가장 짧은 다리 하나를 설치할 수 있다.

이 때 가장 짧은 다리의 길이를 구하는 문제.

 

처음에는 섬을 분리하여, 섬의 가장자리에서 다른 섬의 가장자리로의 최단 거리를 구하려고 했다.

생각해보니 가장자리를 따로 구하지 않고 ,

BFS를 통해 최단 거리를 구하면 하나의 섬의 가장자리에서 다른 섬의 가장자리까지의 거리가 된다. 

 

따라서 DFS 함수에서 각 섬을 구분하고, BFS 함수에서 섬 간의 최단거리를 구했다.

BFS에서 최단거리를 구할 때 시작섬의 좌표를 queue에 모두 넣어줬다.

그리고 하나씩 pop하여 상,하,좌,우 방향으로 퍼져나갔다.

이 때 다른 섬을 만나면 거리를 return 하면서 BFS 함수를 종료하였다. 

 

이와 같은 방식으로 첫번째 섬부터 마지막 섬까지 반복하여  가장 짧은 다리의 길이를 구할 수 있다. 

 

[코드]

 

시간 : 44ms

 

#include <iostream>
#include <queue>
#define MAX 101

using namespace std;

struct pos{
    int x,y;
};

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
int map[MAX][MAX]={0,};
bool tmp[MAX][MAX]={0,};
int N;
int cnt=0;
int answer=MAX*MAX;

void DFS(int x, int y,int cnt)
{
    map[x][y]=cnt;
    tmp[x][y]=true;
    
    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 || tmp[nx][ny] || map[nx][ny]==0 )  continue;
        
        DFS(nx,ny,cnt);
    }
}

int BFS(int idx)
{
    int visited[MAX][MAX]={0,};
    queue <pos> q;
    
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            if(map[i][j]==idx){
                q.push({i,j});
                visited[i][j]=1;
            }
        }
    }
    
    while(!q.empty()){
        int x = q.front().x;
        int y = q.front().y;
        q.pop();

        for(int k=0;k<4;k++){
            int nx = x+dx[k];
            int ny = y+dy[k];
            
            if(nx<0 || ny <0 || nx >= N || ny >= N || visited[nx][ny]!=0 )  continue;
            if(map[nx][ny] !=0 &&  map[nx][ny] != idx)  return visited[x][y]+1;
            
            visited[nx][ny]=visited[x][y]+1;
            q.push({nx,ny});
        }
    }
    return 0;
}


int main(void)
{
    cin >> N;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            cin >> map[i][j];
        }
    }
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            if(map[i][j]==1 && !tmp[i][j]){
                cnt++;
                DFS(i,j,cnt);
            }
        }
    }
    
    for(int i=1;i<cnt;i++)  {
        int res =BFS(i);
        if(res!=0 && res < answer)  answer =res;
    }
    cout << answer-2;
    return 0;
}

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 2589. 보물섬  (0) 2021.01.01
[백준] 5427번. 불  (0) 2020.12.31
[백준] 1937번. 욕심쟁이 판다  (0) 2020.12.28
[백준] 13459. 구슬 탈출  (0) 2020.12.21
[백준] 1744번. 수 묶기  (0) 2020.12.16