엄지월드

백준 2573 빙산(DFS+BFS) 본문

알고리즘

백준 2573 빙산(DFS+BFS)

킨글 2022. 8. 31. 21:38
반응형

문제 접근 방법

1. mapCountDFS를 통해 빙산이 두 덩어리 이상으로 되어 있는지 확인을 진행한다. 

2. globalWarmingBFS를 통해 빙산을 녹여주는 작업을 진행한다. 

헷갈렸던 점

- 빙산이 녹으면서 한번에 모두 0이 되어 덩어리가 0이 되는 경우를 잘못 처리해줬었다.

그래서 녹으면서 한번에 모두 0이 되면 result = 0; 으로 다시 초기화를 진행해주었다.

int result = 0;
while(true){
    int mapCount = countMapDFS();
    if(mapCount == 0){ // 모두 녹아 있을 때에 처리
        result = 0;
        break;
    }
    ...
    ...
}

- 6%에서 계속 틀렸습니다.가 떠서 질문 게시판에 있는 반례를 모두 적용해보았으나, 정상 작동하였다.

그래서 구조를 다시 천천히 보던 중 visited[nx][ny] = true; 처리가 어색한 부분을 발견하였다. 

다음 map[nx][ny] 경로가 0일 때에 visited 처리를 해주면, 다른 경로에서 해당 map[nx][ny] == 0인 경로를 탐색하지 못하게 되기 때문이었다. 

그래서 0인 곳은 방문 처리를 하지 않기 위해 if(map[nx][ny] == 0) continue; 부분 밑으로 내려주어 해결하였다. 

 

<기존>

if(map[nx][ny] == 0 && map[p.x][p.y] > 0){
    map[p.x][p.y] -= 1;
    continue;
}
visited[nx][ny] = true;
if(map[nx][ny] == 0) continue;

q.add(new IceBerg(nx, ny));

<변경>

if(map[nx][ny] == 0 && map[p.x][p.y] > 0){
                    map[p.x][p.y] -= 1;
                    continue;
                }
if(map[nx][ny] == 0) continue;

visited[nx][ny] = true;
q.add(new IceBerg(nx, ny));

소스 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        solution();
    }
    static int N;
    static int M;
    static int map[][];
    static boolean visited[][];
    static int[] dx;
    static int[] dy;
    static void solution() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        map = new int[N][M];
        visited = new boolean[N][M];
        dx = new int[]{-1, 1, 0, 0};
        dy = new int[]{0, 0, -1, 1};

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        int result = 0;
        while(true){
            int mapCount = countMapDFS();
            if(mapCount == 0){ // 모두 녹아 있을 때에 처리
                result = 0;
                break;
            }

            if(mapCount > 1){ // 지역이 2개 이상이면 탈출
                break;
            }
            globalWarmingBFS(); // 녹이기
            result += 1;
        }
        System.out.println(result);
    }
    static class IceBerg{
        int x;
        int y;

        public IceBerg(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    static void dfs(int x, int y){
        visited[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 >= M) continue;
            if(visited[nx][ny] || map[nx][ny] == 0) continue;

            dfs(nx, ny);
        }
    }
    static int countMapDFS(){
        int cnt = 0;
        visited = new boolean[N][M];
        for(int i=0; i<N; i++){
            for (int j = 0; j < M; j++) {
                if(!visited[i][j] && map[i][j] > 0){
                    dfs(i, j);
                    cnt++;
                    if(cnt > 1) return cnt;
                }
            }
        }
        return cnt;
    }
    static void bfs(int x, int y){
        Queue<IceBerg> q = new LinkedList<>();
        q.add(new IceBerg(x, y));
        visited[x][y] = true;

        while(!q.isEmpty()) {
            IceBerg p = q.poll();
            for (int i = 0; i < 4; i++) {
                int nx = p.x + dx[i];
                int ny = p.y + dy[i];

                if(nx < 0 || ny < 0 || nx >= N || ny >= M) continue;
                if(visited[nx][ny]) continue;
                if(map[nx][ny] == 0 && map[p.x][p.y] > 0){
                    map[p.x][p.y] -= 1;
                    continue;
                }
                if(map[nx][ny] == 0) continue;
                
                visited[nx][ny] = true;
                q.add(new IceBerg(nx, ny));
            }
        }
    }
    static void globalWarmingBFS(){
        visited = new boolean[N][M];
        for(int i=0; i<N; i++){
            for (int j = 0; j < M; j++) {
                if(!visited[i][j] && map[i][j] > 0){
                    bfs(i, j);
                }
            }
        }
    }
}

반례 모음

https://www.acmicpc.net/board/view/35110

'알고리즘' 카테고리의 다른 글

성격 유형 검사하기 java  (0) 2022.09.04
오픈채팅방 java  (0) 2022.09.03
백준 1520 내리막길(DFS + DP)  (0) 2022.08.30
백준 2583 영역 구하기  (0) 2022.08.28
42579 (해시)  (2) 2022.08.27
Comments