-
728x90
하루종일 문제를 잡고 늘어지다가, 결국 다른 분의 풀이를 참조해 해결할 수 있었다.
참조 : https://ghkvud2.tistory.com/40
스스로 풀 때는 DFS로 먼저 접근했었는데, 문제에서 원하는 답은 최소 이동 횟수이기에 DFS로 구현하면 이를 찾기가 어려웠다. 예를 들면 다음과 같은 상황 때문이다. (ex) 예제입력 3 좌-좌-좌-좌-좌-좌-하-우-하-좌
물론 턴 수를 기반으로 작은 턴 수를 계속해서 업데이트시키는 방식으로 해결할 수는 있어 보였다. 실제로 다른 분들의 풀이 중 DFS로 해결한 풀이도 있었다. 하지만 이와 같은 최소 이동 개수를 카운트하는 문제에서는 BFS가 더욱 간편하기에 풀이를 변경했다.
최종 풀이 구성을 요약하면 다음과 같다.
- Node 클래스
- int rRow, rCol, bRow, bCol : 각각 red, blue 구슬의 위치
- int cnt : 몇 번 이동했는지 정보
- int bfs(Node ball) 메서드
- 처음 입력정보를 바탕으로 Node를 받아, bfs 방식으로 조건을 만족시키는 최소이동횟수를 탐색한다.
- Queue와 while문을 활용해 최대 10번까지 구슬을 굴려본다
- Node의 정보를 토대로 visited를 확인하며 red, blue 각 구슬의 위치가 이전에 동일한 적이 있다면 다시 방문하지 않는다
- blue 구슬이 구멍에 들어가면 실패
- blue 구슬은 들어가지 않고 red 구슬만 들어가면 성공
- 각각 구슬을 굴린 결과 구멍에 들어가지 않았는데, 서로 구슬의 위치가 같다면 위치를 조정
- int[] rollBlue(int bRow, int bCol, int dir) 메서드
- blue 구슬을 굴리는 메서드
- int[] rollRed(int rRow, int rCol, int dir) 메서드
- red 구슬을 굴리는 메서드
Red, Blue 구슬의 위치를 기준으로 방문한 적이 있는지를 확인하기 위해 boolean 배열 visited를 4차원으로 생성해 활용하는 기술이 시간복잡도를 줄이는데 큰 역할을 한다. 이런 방식으로 차원을 많이 높여 사용해본적이 없어 떠올리지 못했는데, 잘 기억해두면 유용하게 쓸 수 있겠다.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.StringTokenizer; public class Main { static int N, M; static char[][] map; static boolean[][][][] visited; static int[] dirX = new int[] {0, 0, 1, -1}; static int[] dirY = new int[] {1, -1, 0, 0}; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); map = new char[N][M]; visited = new boolean[10][10][10][10]; Node node = new Node(); node.cnt = 0; // map 정보 입력 for(int i = 0; i < N; i++) { String line = br.readLine(); for(int j = 0; j < M; j++) { map[i][j] = line.charAt(j); if(map[i][j] == 'R') { node.rRow = i; node.rCol = j; }else if(map[i][j] == 'B') { node.bRow = i; node.bCol = j; } } } bfs(node); } public static void bfs(Node ball) { Queue<Node> q = new LinkedList<>(); q.offer(ball); while(!q.isEmpty()) { Node node = q.poll(); visited[node.rRow][node.rCol][node.bRow][node.bCol] = true; // 11번 이상 굴린 경우 -1을 출력(0부터 시작하기 때문에 10으로 설정) if(node.cnt >= 10) { System.out.println(-1); return; } // 현재 두 구슬의 위치를 기준으로 동, 서, 남, 북으로 굴려봄 for(int dir = 0; dir < 4; dir++) { int[] bn = rollBlue(node.bRow, node.bCol, dir); int[] rn = rollRed(node.rRow, node.rCol, dir); if(map[bn[0]][bn[1]] == 'O') continue; if(map[rn[0]][rn[1]] == 'O') { System.out.println(node.cnt + 1); return; } // 두 구슬의 위치가 같다면, 위치를 조정한다. if(rn[0] == bn[0] && rn[1] == bn[1]) { if(dir == 0) { if(node.rCol > node.bCol) { bn[1] -= 1; }else { rn[1] -= 1; } }else if(dir == 1) { if(node.rCol > node.bCol) { rn[1] += 1; }else { bn[1] += 1; } }else if(dir == 2) { if(node.rRow > node.bRow) { bn[0] -= 1; }else { rn[0] -= 1; } }else if(dir == 3) { if(node.rRow > node.bRow) { rn[0] += 1; }else { bn[0] += 1; } } } // end of roll // 두 구슬을 굴린 후의 각각 위치가 처음 탐색하는 모양이면 큐에 넣음 if(!visited[rn[0]][rn[1]][bn[0]][bn[1]]) { q.offer(new Node(rn[0], rn[1], bn[0], bn[1], node.cnt + 1)); } } // end of for(동,서,남,북) } // end of while System.out.println(-1); } // 파란색 구슬을 굴린다 public static int[] rollBlue(int bRow, int bCol, int dir) { int[] nxtB = new int[2]; int bnRow = bRow; int bnCol = bCol; while(map[bnRow + dirX[dir]][bnCol + dirY[dir]] != '#') { bnRow += dirX[dir]; bnCol += dirY[dir]; if(map[bnRow][bnCol] == 'O') { break; } } nxtB[0] = bnRow; nxtB[1] = bnCol; return nxtB; } // 빨간색 구슬을 굴린다 public static int[] rollRed(int rRow, int rCol, int dir) { int[] nxtR = new int[2]; int rnRow = rRow; int rnCol = rCol; while(map[rnRow+dirX[dir]][rnCol + dirY[dir]] != '#') { rnRow += dirX[dir]; rnCol += dirY[dir]; if(map[rnRow][rnCol] == 'O') { break; } } nxtR[0] = rnRow; nxtR[1] = rnCol; return nxtR; } } class Node{ int rRow; int rCol; int bRow; int bCol; int cnt; public Node(int rRow, int rCol, int bRow, int bCol, int cnt) { this.rRow = rRow; this.rCol = rCol; this.bRow = bRow; this.bCol = bCol; this.cnt = cnt; } public Node() { } }
'Algorithms' 카테고리의 다른 글
[BOJ] 14502번 연구소 Java 풀이 (0) 2021.06.19 [BOJ] 14890 경사로 Java 풀이 (0) 2021.06.17 [프로그래머스] 카펫 Java 풀이 (0) 2021.05.07 [프로그래머스] 소수 찾기 Java 풀이 (0) 2021.05.07 [프로그래머스] 모의고사 Java 풀이 (0) 2021.05.06 댓글
- Node 클래스