[프로그래머스] 블록 이동하기 - JAVA
https://school.programmers.co.kr/learn/courses/30/lessons/60063
풀이
두 점의 좌표, 방향, 시간을 Node클래스에 담아서 진행했다.
방문처리는 가로를 0, 세로를 1로 놓고 3차원 배열로 처리했다.
이동했을 때 두 점이 모두 방문한 곳이라면 진행시키지 않았다.
귀찮은 구현문제였다.
메모리: 69MB
시간: 5.70ms
언어: Java 11
코드
import java.util.*;
class Solution {
static class Node {
int x1;
int y1;
int x2;
int y2;
int dir;
int cnt;
public Node(int x1, int y1, int x2, int y2, int dir, int cnt) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.dir = dir;
this.cnt = cnt;
}
}
static int[][] vector = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
static int len;
static int[][] board;
static boolean[][][] visit;
static Queue<Node> queue;
public int solution(int[][] board) {
len = board.length;
this.board = board;
return bfs();
}
private static int bfs() {
queue = new LinkedList<>();
visit = new boolean[len][len][2];
addQueue(0, 0, 0, 1, 0, 0);
while(!queue.isEmpty()) {
Node node = queue.poll();
// 도착하면 cnt 반환
if((node.x1 == len - 1 && node.y1 == len - 1) || (node.x2 == len - 1 && node.y2 == len - 1)) {
return node.cnt;
}
// 상하좌우 이동
for(int k = 0; k < 4; k++) {
int nx1 = node.x1 + vector[k][0];
int ny1 = node.y1 + vector[k][1];
int nx2 = node.x2 + vector[k][0];
int ny2 = node.y2 + vector[k][1];
if(outBound(nx1, ny1, nx2, ny2)) {
continue;
}
if(visited(nx1, ny1, nx2, ny2, node.dir)) {
continue;
}
addQueue(nx1, ny1, nx2, ny2, node.dir, node.cnt + 1);
}
// 가로 -> 세로
if(node.dir == 0) {
if(!outBound(node.x1 - 1, node.y1, node.x2 - 1, node.y2)) {
if(!visited(node.x1, node.y1, node.x1 - 1, node.y1, 1)) {
addQueue(node.x1, node.y1, node.x1 - 1, node.y1, 1, node.cnt + 1);
}
if(!visited(node.x2, node.y2, node.x2 - 1, node.y2, 1)) {
addQueue(node.x2, node.y2, node.x2 - 1, node.y2, 1, node.cnt + 1);
}
}
if(!outBound(node.x1 + 1, node.y1, node.x2 + 1, node.y2)) {
if(!visited(node.x1, node.y1, node.x1 + 1, node.y1, 1)) {
addQueue(node.x1, node.y1, node.x1 + 1, node.y1, 1, node.cnt + 1);
}
if(!visited(node.x2, node.y2, node.x2 + 1, node.y2, 1)) {
addQueue(node.x2, node.y2, node.x2 + 1, node.y2, 1, node.cnt + 1);
}
}
}
// 세로 -> 가로
else {
if(!outBound(node.x1, node.y1 - 1, node.x2, node.y2 - 1)) {
if(!visited(node.x1, node.y1, node.x1, node.y1 - 1, 0)) {
addQueue(node.x1, node.y1, node.x1, node.y1 - 1, 0, node.cnt + 1);
}
if(!visited(node.x2, node.y2, node.x2, node.y2 - 1, 0)) {
addQueue(node.x2, node.y2, node.x2, node.y2 - 1, 0, node.cnt + 1);
}
}
if(!outBound(node.x1, node.y1 + 1, node.x2, node.y2 + 1)) {
if(!visited(node.x1, node.y1, node.x1, node.y1 + 1, 0)) {
addQueue(node.x1, node.y1, node.x1, node.y1 + 1, 0, node.cnt + 1);
}
if(!visited(node.x2, node.y2, node.x2, node.y2 + 1, 0)) {
addQueue(node.x2, node.y2, node.x2, node.y2 + 1, 0, node.cnt + 1);
}
}
}
}
return -1;
}
// 범위 벗어나는 경우 판단
private static boolean outBound(int x1, int y1, int x2, int y2) {
if(x1 < 0 || y1 < 0 || x1 >= len || y1 >= len) {
return true;
}
if(x2 < 0 || y2 < 0 || x2 >= len || y2 >= len) {
return true;
}
if(board[x1][y1] == 1 || board[x2][y2] == 1) {
return true;
}
return false;
}
// 방문했던 곳인지 판단
private static boolean visited(int x1, int y1, int x2, int y2, int dir) {
if(visit[x1][y1][dir] && visit[x2][y2][dir]) {
return true;
}
return false;
}
// 방문처리 & 큐에 삽입
private static void addQueue(int x1, int y1, int x2, int y2, int dir, int cnt) {
visit[x1][y1][dir] = true;
visit[x2][y2][dir] = true;
queue.add(new Node(x1, y1, x2, y2, dir, cnt));
}
}