BOJ 19236 청소년 상어

메모리 : 13244 KB

시간 : 84 ms

BOJ 19236 청소년 상어


풀이

깊은복사, 얕은복사 때문인지도 모르고 답이 안 나와서 코드 삭제 4번은 한 듯 하다.

그래서 로직 문제인 줄 알고 다른 사람 코드도 참고 많이 하다보니 내 코드가 많이 사라진 것 같다.. 주석도 많이 사라지고.. 주석이 사라진 게 좀 아쉽다

물고기들이 순서대로 움직인다고 해서 처음에 ArrayList로 관리했는데 점점 복잡해져서

배열로 바꾸고 클래스 안에 죽었는지 살았는지 확인할 수 있는 boolean 변수를 넣어주었다.

상어가 이렇게 갔다가 저렇게 갔다가 해야되는데 대체 어떻게 해야 되지 엄청 고민했다. 어떻게 하는진 알겠는데 코드로 어떻게 짜야 좋을지 모르겠는 그런 상태였었다.

근데 배열 복사해서 재귀함수에 보내주는 게 아니라 재귀함수 들어갔다 나와서 원상복구 시켜주면 답이 또 다르게 나오던데 왜 그러는걸까..? 스터디 할 때 친구들한테 물어봐야겠다.


느낀점

깊은 복사, 얕은 복사 제대로 이해하고 넘어가자

완전탐색 연습 많이 하자


코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class BOJ19236 {
  static int ans;
  static int[][] dir = {{-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = null;
		
    int[][] map = new int[4][4];
    Fish[] fish = new Fish[17];
		
    for (int i = 0; i < 4; i++) {
      st = new StringTokenizer(br.readLine(), " ");
      for (int j = 0; j < 4; j++) {
        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken()) - 1;
        map[i][j] = a;
        fish[a] = new Fish(i, j, b, false);
      }
    }
		
    int die = map[0][0];
    map[0][0] = 0;
    fish[die].dead = true;
    int sharkDir = fish[die].dir;
		
    move(map, fish, 0, 0, sharkDir, die); // 맵, 물고기, 상어 좌표 x, y, 상어 방향, 합
		
    System.out.println(ans);
  }
	
  private static void move(int[][] map, Fish[] fish, int sx, int sy, int sd, int sum) {
    // 물고기 이동
    for (int i = 1; i <= 16; i++) {
      if(fish[i].dead) continue;
			
      int fx = fish[i].x;
      int fy = fish[i].y;
      int fd = fish[i].dir;
			
      for (int j = 0; j < 8; j++) {
        int nd = (fd + j) % 8;
        int nx = fx + dir[nd][0];
        int ny = fy + dir[nd][1];
				
        // 범위를 벗어나거나 상어가 있으면 방향을 바꾼다
        if(!isRange(nx, ny)) continue;
        if(map[nx][ny] == 0) continue;
				
        if(map[nx][ny] > 0) { // 다른 물고기가 있으면 서로 자리를 바꿈
          int tmp = map[nx][ny];
          map[nx][ny] = i;
          map[fx][fy] = tmp;
          fish[i].x = nx;
          fish[i].y = ny;
          fish[i].dir = nd;
          fish[tmp].x = fx;
          fish[tmp].y = fy;
          break;
        } else { // 빈칸이면
          map[nx][ny] = i;
          map[fx][fy] = -1;
          fish[i].x = nx;
          fish[i].y = ny;
          fish[i].dir = nd;
          break;
        }
      }
    }
		
    // 상어 이동
    boolean flag = false;
		
    for (int i = 1; i <= 3; i++) {
      int nsx = sx + i * dir[sd][0];
      int nsy = sy + i * dir[sd][1];
		
      int[][] map2 = new int[4][4];
      Fish[] fish2 = new Fish[17];
			
      for (int j = 0; j < 4; j++) {
        for (int j2 = 0; j2 < 4; j2++) {
          map2[j][j2] = map[j][j2];
        }
      }
			
      for (int j = 1; j <= 16; j++) {
        fish2[j] = new Fish();
        fish2[j].x = fish[j].x;
        fish2[j].y = fish[j].y;
        fish2[j].dir = fish[j].dir;
        fish2[j].dead = fish[j].dead;
      }
			
      if(isRange(nsx, nsy) && map2[nsx][nsy] > 0) {
        int die = map2[nsx][nsy];
        map2[nsx][nsy] = 0;
        map2[sx][sy] = -1;
        fish2[die].dead = true;
        int nsd = fish2[die].dir;
				
        move(map2, fish2, nsx, nsy, nsd, sum+die);

        flag = true;
      }
    }
		
    if(!flag) {
      ans = Math.max(ans, sum);
      return;
    }
  }
	
  static boolean isRange(int x, int y) {
    return 0<=x && x<=3 && 0<=y && y<=3;
  }

  static class Fish {
    int x, y, dir;
    boolean dead;
		
    public Fish() { }
		
    public Fish(int x, int y, int dir, boolean dead) {
      super();
      this.x = x;
      this.y = y;
      this.dir = dir;
      this.dead = dead;
    }

    @Override
    public String toString() {
      return "Fish [x=" + x + ", y=" + y + ", dir=" + dir + ", dead=" + dead + "]";
    }
  }
}