developer-ellen
인간 디버거의 로그 찍기
developer-ellen
전체 방문자
오늘
어제
  • 분류 전체보기 (217)
    • 회고록 (0)
    • 취뽀 및 커리어 여정의 Stack (2)
      • SSAFY 7기 (2)
    • 프로그래밍공부 (24)
      • c++ (0)
      • JAVA (3)
      • Spring (5)
      • design pattern (3)
      • BackDB (1)
      • Servlet&JSP (3)
      • Vue (4)
      • JPA (4)
      • Infra (1)
      • Linux (0)
    • AI (3)
      • papers (3)
      • trend (0)
    • 프로젝트진행 (0)
      • 데이터베이스 (0)
      • 서버개발 (0)
      • 인공지능 (0)
      • 하루정리 (0)
    • 포트폴리오 (0)
    • 알고리즘 (158)
      • 알고리즘문풀 (155)
      • 알고리즘공부 (3)
    • 통계공부 (15)
      • 시계열분석 (15)
      • 회귀분석 (0)
    • CS (14)
      • 컴퓨터네트워크 (4)
      • 운영체제 (8)
      • 데이터베이스 (2)
    • 주저리주저리 (0)
      • 필사 (0)
    • 취업관련정보 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 삼성코테자바풀이
  • 백준파이썬풀이
  • BOJ파이썬풀이
  • 카카오코테java풀이
  • 삼성코테자바준비
  • SW역량테스트파이썬
  • 코테파이썬
  • Arima
  • 데이터분석
  • 삼성코테준비
  • 삼성코테파이썬
  • 삼성코테구현풀이
  • c++ 빌더 패턴
  • 통계학
  • AR모형
  • SW역량테스트파이썬풀이
  • 삼성코테파이썬풀이
  • MA모형
  • 카카오코테
  • 삼성코테구현문제추천
  • ARIMA모형
  • 운영체제인터럽트
  • 삼성코테기출자바풀이
  • 시계열
  • 통계분석
  • 시계열분석
  • 삼성코테기출
  • 삼성코테파이썬준비
  • c++디자인패턴
  • 삼성코테자바꿀팁

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

알고리즘/알고리즘문풀

BOJ - 빙산 2573번 (JAVA)

2022. 2. 19. 19:41

❓ 문제 - 백준 빙산 2573번 - JAVA 풀이법

 

출처 

(https://www.acmicpc.net/problem/2573)

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

 

 

📝 문제해결법

1. 이 문제는 DFS 풀이로 해결하였다.

2. while문을 통해 얼음이 존재하는 지 check() → true: 얼음 존재 하지 않으므로 while문 break

3. 1년 증가 후 얼음 감소 down() 처리

  • 2차원 배열 map의 얼음감소를 저장할 copy 배열
  • 왜 copy 배열에 감소된 얼음양을 저장 ? → 1년 안에 한번에 얼음이 사라지므로, 2중 for문 돌다가 map 배열에 감소된 값 저장되면 다음 for문 돌 때 영향을 줄 수 있기 때문
  • 2차원 배열 map 돌면서 만약 얼음이 존재(1이상의 값)한다면 상,하,좌,우 돌면서 인접한 곳에 얼마나 바다 있느지 체크 후, 얼음 수를 바다 수만큼 감소
  • 그러나, 현재 가진 얼음 양보다 인접한 바다 수 많다면 0으로 copy 배열에 저장
  • 사라진 후 얼음의 정보를 담은 copy 배열의 값을 map에 복사

4. dfs() → 얼음 덩어리 갯수 찾기

  • 얼음이 존재하는 곳에 4방향으로 인접한 곳 돌면서 만약 얼음덩어리가 존재 한다면 재귀 탐색 dfs()
  • dfs() 빠져나오면 한 덩어리가 visited 2차원 배열에 true 표시, 얼음덩어리 카운트 1증가
  • dfs() 다 돌아서 만약 얼음덩어리 갯수가 2개 이상이면 while문 break

 

 

5. 느낀점

  • 1년 안에 얼음 감소는 같이 일어나므로 감소하면서 바로 map 배열에 변경 처리 하면 영향을 받는다를 꼭 명심...

 

💻 소스코드

// BOJ - 빙하(2573번)
// DFS 구현
// 메모리 : 135940KB, 시간 :	524ms

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class DFS_BOJ_2573_LSH {
    public static int[][] map;
    public static int n, m;
    public static boolean[][] visited;
    public static int[] dx = {-1, 1, 0, 0};
    public static int[] dy = {0, 0, -1, 1};
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] data = br.readLine().split(" ");
        n = Integer.parseInt(data[0]);
        m = Integer.parseInt(data[1]);
        map = new int[n][m];
        // map에 대한 정보를 받는 부분
        for(int i=0;i<n;i++){
            String[] input = br.readLine().split(" ");
            for(int j=0;j<m;j++){
                map[i][j] = Integer.parseInt(input[j]);
            }
        }

        boolean check = false;
        int year = 0;
        while (true){
            // 만약 map에 얼음이 존재하지 않는다면 --> true 값이므로 check= true로 변경해주고 while문 빠져나오기

            if(check()){
                check = true;
                break;
            }
            // 1년이 증가
            // down()을 통해 얼음의 양 감소 처리
            year++;
            down();
            // ice는 얼음덩어리의 갯수를 체크 해줌
            int ice = 0;
            // dfs에서 방문 처리를 체크할 visited 배열
            visited = new boolean[n][m];
            // map을 돌면서 dfs룰 통해 아직 방문처리 되지 않고, 얼음이라면 얼만큼 얼음이 이어진지 처리
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(map[i][j] > 0 && !visited[i][j]){
                        ice++;
                        dfs(i, j);


                    }
                }
            }
            // dfs를 통해 얼음 덩어리의 갯수가 2 이상이라면 while문 빠져나가게 됨
            if(ice>= 2){
                break;
            }


        }

        // 위에 check()라는 함수를 통해서 만약 아직 덩어리가 2개 이상으로 쪼개지지 않았는데 map에 얼음이 존재하지 않는 상태
        // check가 true 라면 0 출력
        if(check){
            System.out.println("0");
        } else {
            System.out.println(year); // while을 통해 증가시킨 year 값 출력
        }

    }
    // dfs 함수로 하나의 얼음덩어리를 만나면 체크
    public static void dfs(int x, int y){
       visited[x][y] = true;
       for(int d=0;d<4;d++){
           int nx = x + dx[d];
           int ny = y + dy[d];
           if (0 <= nx && nx < n && 0 <= ny && ny < m) {
               // 상,하,좌,우로 얼음덩이리가 있다면 재귀를 들어가면서 탐색
               if(map[nx][ny] > 0 && !visited[nx][ny]) dfs(nx, ny);
           }
       }
    }

    // copy라는 배열을 통해 1년동안 바다 상,하,좌,우에 있는 얼음이 주변에 바다가 있는 만큼 얼음양 감소
    // 감소는 1년 안에 일어나기 때문에 copy라는 새로운 배열에 변경된 값 넣어줌
    // 그리고 마지막에 실제 map에 값을 바꿔줘야함
    public static void down(){
        int[][] copy = new int[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                int zero_cnt = 0;
                // 만약 map 행, 열 돌면서 얼음이 있다면
                if(map[i][j] > 0) {
                    // 상,하,좌,우로 돌면서 해당 위치의 4방향에 얼만큼 바다가 있는지 카운트
                    for (int d = 0; d < 4; d++) {
                        int nx = i + dx[d];
                        int ny = j + dy[d];
                        if (0 <= nx && nx < n && 0 <= ny && ny < m) {
                            if (map[nx][ny] == 0) zero_cnt++;
                        }
                    }
                    //만약 현재 자기가 가진 얼음양보다 바다의 개수가 더 많으면 0으로 값
                    //아니면 자기가 가진 얼음의 양 - 바다의 갯수
                    if(map[i][j] < zero_cnt){
                        copy[i][j] = 0;
                    } else {
                        copy[i][j] = (map[i][j] - zero_cnt);
                    }
                }

            }
        }
        // 마지막으로 copy 배열을 실제 map 2차원 배열에 값을 copy 해줌
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                map[i][j] = copy[i][j];
            }
        }
    }

    // 바다에 얼음이 존재하는지 체크하는 함수
    // 만약 한 곳이라도 얼음이 존재한다면 false 반환
    // 만약 얼음이 다 사라졌다면 true 반환
    public static boolean check(){
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(map[i][j] > 0) return false;
            }
        }
        return true;
    }
}

'알고리즘 > 알고리즘문풀' 카테고리의 다른 글

BOJ - 마법사 상어와 복제 23290번 (JAVA)  (0) 2022.03.01
BOJ - 입국심사 3079번 (JAVA)  (0) 2022.02.21
SW Expert Academy - 무선 충전 (JAVA)  (0) 2022.02.17
BOJ - 전구와 스위치 2138번 (JAVA)  (0) 2022.02.16
BOJ - 상어 초등학교 21608번 (JAVA)  (0) 2022.02.11
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • BOJ - 마법사 상어와 복제 23290번 (JAVA)
    • BOJ - 입국심사 3079번 (JAVA)
    • SW Expert Academy - 무선 충전 (JAVA)
    • BOJ - 전구와 스위치 2138번 (JAVA)
    developer-ellen
    developer-ellen

    티스토리툴바