Record

BAEK19237. 어른 상어 본문

Algorithm/BOJ

BAEK19237. 어른 상어

윤프라이즈 2023. 6. 27. 15:40

2023년 6월 27일

https://www.acmicpc.net/problem/19237

시간 : ❤🤍🤍🤍🤍

만족도 : ❤🤍🤍🤍🤍


특별한 알고리즘은 없지만 구현이 까다로운 문제이다.

Queue를 사용해서 상어들을 큐에 넣어서 해결하려고 하다가 도저히 풀리지가 않아서

다른 방법으로 해결해보았다.


  • 코드

      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStreamReader;
      import java.sql.Array;
      import java.util.*;
    
      public class BAEK19237 {
          static class Shark {
              int x;
              int y;
              int dir;
              public Shark (int x, int y, int dir) {
                  this.x = x;
                  this.y = y;
                  this.dir = dir;
              }
          }
          static int N, M, K;
          static int[] dx = {0, -1, 1, 0, 0};
          static int[] dy = {0, 0, 0, -1, 1};
          // 냄새가 없어질 때까지 남은 시간
          static int[][] rest;
          // 냄새를 뿌린 상어의 번호
          static int[][] smell;
          // 상어의 우선순위 방향
          static int[][][] priorDir;
          // 상어의 정보를 담을 배열
          static Shark[] shark;
          public static void main(String[] args) throws IOException {
              BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
              StringTokenizer st = new StringTokenizer(br.readLine());
              // N * N 격자의 크기
              N = Integer.parseInt(st.nextToken());
              // 상어의 마리수
              M = Integer.parseInt(st.nextToken());
              // 냄새가 사라지는 시간
              K = Integer.parseInt(st.nextToken());
    
              rest = new int[N+1][N+1];
              smell = new int[N+1][N+1];
              priorDir = new int[M+1][5][4];
              shark = new Shark[M+1];
    
              for (int i = 1; i <= N; i++) {
                  st = new StringTokenizer(br.readLine());
                  for (int j = 1; j <= N; j++) {
                      int num = Integer.parseInt(st.nextToken());
                      if (num > 0) {
                          shark[num] = new Shark(i, j, 0);
                          // 해당 칸에 냄새가 사라지는 시간 초기화
                          rest[i][j] = K;
                          // 냄새를 어떤 상어가 남겼는지 초기화
                          smell[i][j] = num;
                      }
                  }
              }
    
              st = new StringTokenizer(br.readLine());
              for (int i = 1; i <= M; i++) {
                  shark[i].dir = Integer.parseInt(st.nextToken());
              }
    
              for (int i = 1; i <= M; i++) {
                  for (int j = 1; j <= 4; j++) {
                      st = new StringTokenizer(br.readLine());
                      for (int k = 0; k < 4; k++) {
                          priorDir[i][j][k] = Integer.parseInt(st.nextToken());
                      }
                  }
              }
              System.out.println(solution());
          }
          public static int solution() {
              int time = 0;
              while(true) {
                  int count = 0;
    
                  for (int i = 1; i <= M; i++) {
                      if (shark[i] != null) count++;
                  }
    
                  // 1번 상어만 남았을 경우
                  if (count == 1 && shark[1] != null) return time;
    
                  // 1000번 이상일 경우
                  if (time >= 1000) return -1;
    
                  int[][] temp = new int[N+1][N+1];
    
                  for (int i = 1; i <= M; i++) {
                      // 해당 번호의 상어가 있다면
                      if (shark[i] != null) {
                          moveShark(temp, i);
                      }
                  }
    
                  // 냄새 기간 줄이기
                  for (int i = 1; i <= N; i++) {
                      for (int j = 1; j <= N; j++) {
                          if (rest[i][j] > 0) rest[i][j]--;
                          if (rest[i][j] == 0) smell[i][j] = 0;
                      }
                  }
    
                  // 이동 후의 상어 위치의 냄새 정보와 시간 초기화하기
                  for (int i = 1; i <= N; i++) {
                      for (int j = 1; j <= N; j++) {
                          if (temp[i][j] > 0) {
                              rest[i][j] = K;
                              smell[i][j] = temp[i][j];
                          }
                      }
                  }
                  time++;
              }
          }
          public static void moveShark(int[][] temp, int num) {
              int nx = 0;
              int ny = 0;
              int dir = 0;
    
              boolean check = false;
    
              // 높은 우선순위부터 차례대로 탐색
              for (int i = 0; i < 4; i++) {
                  dir = priorDir[num][shark[num].dir][i];
                  nx = shark[num].x + dx[dir];
                  ny = shark[num].y + dy[dir];
    
                  if (nx < 1 || nx > N || ny < 1 || ny > N) continue;
    
                  if (smell[nx][ny] == 0) {
                      check = true;
                      break;
                  }
              }
    
              // 위의 반복문에서 아무곳도 못갔을 경우
              if (!check) {
                  for (int i = 0; i < 4; i++) {
                      dir = priorDir[num][shark[num].dir][i];
                      nx = shark[num].x + dx[dir];
                      ny = shark[num].y + dy[dir];
    
                      if (nx < 1 || nx > N || ny < 1 || ny > N) continue;
    
                      if (smell[nx][ny] == num) {
                          break;
                      }
                  }
              }
    
              if (temp[nx][ny] == 0) {
                  temp[nx][ny] = num;
                  shark[num].x = nx;
                  shark[num].y = ny;
                  shark[num].dir = dir;
              }
    
              // 이미 번호가 작은 상어가 위치해있다는 뜻이므로 잡아먹힌다.
              else shark[num] = null;
          }
      }

'Algorithm > BOJ' 카테고리의 다른 글

BAEK21609. 상어 중학교  (1) 2023.12.06
BAEK20056. 마법사 상어와 파이어볼  (2) 2023.12.05
BAEK3986. 좋은 단어  (0) 2023.06.26
BAEK10799. 쇠막대기  (0) 2023.06.25
BAEK1406. 에디터  (0) 2023.06.25
Comments