[랜덤 마라톤] Bacteria (Small)(12567)

lhs's avatar
Dec 28, 2024
[랜덤 마라톤] Bacteria (Small)(12567)
notion image
notion image

1. 문제 풀이 아이디어

  • 박테리아가 번식할 수 있는 가장 큰 테두리를 구한 뒤, 테두리의 최대 x좌표와 최대 y좌표를 더한 값에서 최소 x+y 좌표의 합을 뺀 뒤 1을 더하면 문제를 해결할 수 있다.
  • 가장 큰 테두리는 BFS를 활용해 동, 서, 남, 북, 남서, 북동 방향으로 탐색하여 구한다.

2. 나의 정답 코드

public class Main { public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); StringBuilder stringBuilder = new StringBuilder(); int t = Integer.parseInt(bufferedReader.readLine()); int[][] dir = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {-1, 1}, {1, -1}}; for (int i = 0; i < t; i++) { int n = Integer.parseInt(bufferedReader.readLine()); boolean[][] v = new boolean[102][102]; boolean[][] map = new boolean[102][102]; List<int[]> list = new ArrayList<>(); Queue<int[]> queue = new ArrayDeque<>(); for (int j = 0; j < n; j++) { StringTokenizer stringTokenizer = new StringTokenizer(bufferedReader.readLine()); int x1 = Integer.parseInt(stringTokenizer.nextToken()); int y1 = Integer.parseInt(stringTokenizer.nextToken()); int x2 = Integer.parseInt(stringTokenizer.nextToken()); int y2 = Integer.parseInt(stringTokenizer.nextToken()); for (int x = x1; x <= x2; x++) { for (int y = y1; y <= y2; y++) { map[x][y] = true; list.add(new int[]{x, y}); } } } int result = 0; for (int[] cur : list) { if (v[cur[0]][cur[1]]) continue; v[cur[0]][cur[1]] = true; int maxX = 0; int maxY = 0; int minXY = Integer.MAX_VALUE; queue.add(cur); while (!queue.isEmpty()) { cur = queue.poll(); maxX = Math.max(maxX, cur[0]); maxY = Math.max(maxY, cur[1]); minXY = Math.min(minXY, cur[0] + cur[1]); for (int[] d : dir) { int[] next = {cur[0] + d[0], cur[1] + d[1]}; if (v[next[0]][next[1]]) continue; v[next[0]][next[1]] = true; if (!map[next[0]][next[1]]) continue; queue.add(next); } } result = Math.max(result, maxX + maxY - minXY + 1); } stringBuilder.append("Case #").append(i + 1).append(": ").append(result).append('\n'); } System.out.print(stringBuilder); bufferedReader.close(); } }

3. 정리

  • 박테리아 좌표는 두 가지 자료구조에 저장한다.
    • 리스트는 BFS 탐색 시 빠르게 박테리아를 찾아내기 위해 사용하며, 배열은 탐색 방향에 따라 효율적으로 접근하기 위해 활용한다.
  • 리스트에서 박테리아의 좌표를 순회하며 BFS 탐색을 진행한다.
  • BFS 탐색은 동, 서, 남, 북, 남서, 북동 방향으로 이루어지며, vmap 2차원 배열을 사용해 다음 탐색할 박테리아를 찾는다.
  • 탐색 중 최대 x좌표, 최대 y좌표, 최소 x+y 좌표를 계산한다.
  • 탐색이 끝난 뒤, 현재 탐색된 테두리의 결과값이 더 크면 결과값을 갱신한다.
  • 리스트는 박테리아를 빠르게 찾아 bfs로 탐색하기 위해, 배열의 경우 탐색 방향으로 접근을 위해 박테리아의 좌표를 두 가지 자료구조로 저장한다.

4. 시행착오

  • 첫 번째 시도에서 단순 while문 구현으로 해결하려 했으나 시간 초과로 실패했다.
    • 단순 구현으로도 해결된다고 했으나 Java에서는 시간이 부족했거나 잘못된 정보였다.
  • 두 번째 시도에서는 누적 계산으로 해결하려 했으나 실패했다.
    • 박테리아가 사라지는 경우를 고려하지 않아 단순 누적 계산으로는 해결이 불가능했다.
  • 세 번째 시도에서는 BFS 탐색을 시도했지만, 북서쪽도 탐색 방향에 포함시켜 실패했다.
    • 서쪽에 박테리아가 없고 북서쪽에만 박테리아가 있을 경우, 연결된 테두리가 아니다.
    • 예시
    • 0101 0000 0000 1010 0101 0000 0101 0000 0000 0000 0000 1110 0111 0011 0001 0000
  • map[x][y]로 2차원 배열을 순회하며 박테리아 좌표를 찾는 것보다 리스트로 좌표를 저장해 사용하는 방식이 훨씬 효율적이었다.

5. 테스트 케이스

Share article

LHS's Study Space