[백준] 5547번: 일루미네이션

ByWindow·2021년 6월 29일
0

Algorithm

목록 보기
32/104
post-thumbnail

📝문제

  • 초기 접근 방식

    외벽을 세는 방법은 graph[i][j]의 값이 1일 때, 그 곳이 주변의 0과 만나는 변을 카운트하면 되겠다고 생각했다. 그래서 건물의 외벽인 곳(값이 1인 곳)을 한 점 찾아서 dfs로 주변의 벽을 탐색하는 방법으로 풀려고 했다.
    하지만 건물 안쪽에 빈 곳이 있으면 그부분은 카운트하지 않아야하는데 도저히 이 방법으로는 그것을 판단할 수 없었다.

  • 수정안

    건물의 외벽의 바깥 부분의 빈 공간에 표시를 한다.
    그리고 graph[i][j]가 1인 곳이 방금 표시해둔 곳과 인접할 때, 그것만 카운트를 한다.
    이렇게 하면 건물 안쪽에 빈 공간에 대해서는 표시를 하지 않기 때문에 초기 접근 방식에서 발견한 허점을 보완할 수 있다.
    건물 외벽의 바깥 부분을 찾기 위해서는 맨처음의 빈공간에 대해서 bfs 알고리즘으로 인접한 graph[i][j]가 0인 곳을 추가해주며 표시하면 된다.

📌코드

package Baekjoon;

import java.util.*;
import java.io.*;

/**
 * 0과 1이 만나는 곳을 찾으면 된다
 * 0인 곳과 1인 곳이 인접하면 그 면은 외부
 * 가장자리에 있는 면은 따로 기록
 */

public class BOJ5547 {

  static int w;
  static int h;
  static int[][] graph;
  static boolean[][] isOut;
  static int[][] moveOdd = {{-1, 0}, {0, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
  static int[][] moveEven = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1 ,0}};
  static Queue<int[]> q = new LinkedList<>();

  static void checkingOuter(int[][] moving, int curRow, int curCol, int i) {

    int nextRow = curRow + moving[i][0];
    int nextCol = curCol + moving[i][1];
    if(nextRow >= 0 && nextRow <= h+1 && nextCol>=0 && nextCol<=w+1){
      if(!isOut[nextRow][nextCol]){
        if(graph[nextRow][nextCol] == 0){
          isOut[nextRow][nextCol] = true;
          q.offer(new int[] {nextRow, nextCol});
        }
      }
    }
  }

  public static void main(String[] args) throws IOException{

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = new StringTokenizer(br.readLine());

    w = Integer.parseInt(st.nextToken());
    h = Integer.parseInt(st.nextToken());
    graph = new int[h+2][w+2];
    isOut = new boolean[h+2][w+2];

    for(int i = 1; i < h+1; i++){
      st = new StringTokenizer(br.readLine());
      for (int j = 1; j < w+1; j++){
        graph[i][j] = Integer.parseInt(st.nextToken());
      }
    }

    //벽으로 둘러싸인 곳을 제외하기 위해 건물의 벽 외부의 여백에만 isOut을 표시해둔다
    q.offer(new int[]{0, 0}); //{row, col}
    isOut[0][0] = true;

    while(!q.isEmpty()){
      int[] cur = q.poll();
      int curRow = cur[0];
      int curCol = cur[1];
      for(int i = 0; i < 6; i++){
        if(curRow % 2 == 0){
          checkingOuter(moveEven, curRow, curCol, i);
        } else {
          checkingOuter(moveOdd, curRow, curCol, i);
        }
      }
    }

    int answer = 0;
    for(int i = 1; i < h+1; i++){
      for(int j = 1; j < w+1; j++){
        if(graph[i][j] == 0) continue;
        for(int n = 0; n < 6; n++){
          int nextRow;
          int nextCol;
          if(i%2 == 0){
            nextRow = i + moveEven[n][0];
            nextCol = j + moveEven[n][1];
          }else{
            nextRow = i + moveOdd[n][0];
            nextCol = j + moveOdd[n][1];
          }
          if(isOut[nextRow][nextCol]) answer++;
        }
      }
    }
    System.out.println(answer);
  }
}
profile
step by step...my devlog

0개의 댓글