[BOJ] 1938. 통나무 옮기기
저는 기본적으로 통나무의 위치를 가운데 좌표와 모양(세로/가로)의 정보로 파악했습니다.
bfs로 진행
** 4차원의 visit 배열
통나무 모양에 따라서
5가지 행위에 대해서
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.Queue; //BOJ :: 1938 통나무 옮기기 public class Main1938_통나무옮기기2 { private static char[][] map; private static boolean[][][][] visit; private static int N; private static ArrayList<pair> nowLog; private static ArrayList<pair> destLog; private static log end; public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); N = Integer.parseInt(br.readLine()); nowLog = new ArrayList<>(); destLog = new ArrayList<>(); map = new char[N][N]; visit = new boolean[5][2][N][N]; for (int i = 0; i < N; i++) { String str = br.readLine(); for (int j = 0; j < N; j++) { map[i][j] = str.charAt(j); if (map[i][j] == 'B') nowLog.add(new pair(i, j)); if (map[i][j] == 'E') destLog.add(new pair(i, j)); } } //// input Collections.sort(nowLog); Collections.sort(destLog); int type; if (nowLog.get(0).y == nowLog.get(1).y) type = 2; else type = 1; log start = new log(nowLog.get(1).y, nowLog.get(1).x, type, 0); if (destLog.get(0).y == destLog.get(1).y) type = 2; else type = 1; end = new log(destLog.get(1).y, destLog.get(1).x, type, 0); System.out.println(bfs(start)); } // end of main static int[] dy = { -1, 1, 0, 0, -1, -1, 1, 1 }; static int[] dx = { 0, 0, -1, 1, -1, 1, -1, 1 }; // 상하좌우//대각선 public static int bfs(log start) { Queue<log> q = new LinkedList<>(); q.add(start); // visit[][start.type-1][start.y][start.x] = true; while (!q.isEmpty()) { log now = q.poll(); int y = now.y; int x = now.x; // 통나무의 mid 정보 int type = now.type; int cnt = now.cnt; // 종료조건 확인 if (y == end.y && x == end.x && type == end.type) { return cnt; } for (int i = 0; i < 5; i++) { if (i == 4) { // 회전 boolean isPossible = true; // 회전할 수 있는 범위 확인. for (int chk = 0; chk < 8; chk++) { int ny = y + dy[chk]; int nx = x + dx[chk]; if (ny < 0 || ny > N - 1 || nx < 0 || nx > N - 1 || map[ny][nx] == '1') { isPossible = false; break; } } if (!isPossible) continue; int ntype; if (type == 1) ntype = 2; else ntype = 1; if (!visit[i][type - 1][y][x]) { q.add(new log(y, x, ntype, cnt + 1)); visit[i][type - 1][y][x] = true; } } else if (i < 4) {// 상하좌우 이동 int ny = y + dy[i]; int nx = x + dx[i]; if (ny < 0 || ny > N - 1 || nx < 0 || nx > N - 1 || map[ny][nx] == '1' || visit[i][type - 1][ny][nx]) continue; if (type == 1) { // | int topY = ny - 1; int bottomY = ny + 1; if (topY < 0 || bottomY > N - 1 || map[topY][nx] == '1' || map[bottomY][nx] == '1') continue; } else { // - int leftX = nx - 1; int rightX = nx + 1; if (leftX < 0 || rightX > N - 1 || map[ny][leftX] == '1' || map[ny][rightX] == '1') continue; } visit[i][type - 1][ny][nx] = true; q.add(new log(ny, nx, type, cnt + 1)); } } } return 0; } static class log { int y; int x; int type; // 1 : | // 2: - int cnt; public log(int y, int x, int type, int cnt) { super(); this.y = y; this.x = x; this.type = type; this.cnt = cnt; } } static class pair implements Comparable<pair> { int y; int x; public pair(int y, int x) { super(); this.y = y; this.x = x; } @Override public int compareTo(pair o) { if (o.x == this.x) return o.x - this.x; else if (o.y == this.y) { return o.y - this.y; } return -1; } } } | cs |
'Algorithm Problem Solving' 카테고리의 다른 글
[BOJ] 16235 : 나무재테크 (1) | 2019.04.13 |
---|---|
[BOJ] 15685. 드래곤 커브 (5) | 2019.04.09 |
[SWEA] 2383. 점심식사 시간 (5) | 2019.04.04 |
[SWEA] 1949. 등산로 조성 (0) | 2019.04.01 |
[BOJ] 1805. 나무자르기 (4) | 2019.03.22 |