| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
Tags
- Stack
- 컴퓨터비전
- 임베디드
- 2018 KAKAO BLIND RECRUITMENT
- 통신 인터페이스
- 다이나믹 프로그래밍
- 동적계획법
- BFS
- c++
- dp
- 이분탐색
- 프로그래머스
- level3
- dfs
- 누적합
- 우선순위큐
- 구현
- 그리디
- 다이나믹프로그래밍
- JavaScript
- 자바
- lv2
- C
- level2
- 코틀린
- kotlin
- cpp
- 백준
- 컴퓨터 비전
- java
Archives
- Today
- Total
코드를 느껴바라
Lv.3 [PCCP 기출문제] 4번 / 수레 움직이기 [JAVA] 본문
문제링크
성공 여부(걸린 시간): 성공(1시간 20분 21초)
아이디어
두 수레(빨간/파란)를 동시에 이동시키며 각각 도착지에 도달하는 데 필요한 최소 이동 횟수를 구해야 한다.
두 수레는 다음 조건들을 만족하며 이동해야 한다.
- 서로 같은 칸을 동시에 점유할 수 없음
- 서로 자리를 교차해 지나갈 수 없음
- 도착지에 도착한 수레는 더 움직이지 않음
- 각 수레는 이미 자신이 이동했던 칸을 다시 방문할 수 없음
- 벽(5)은 이동 불가
- BFS 사용
- 상태는
{R_x, R_y, B_x, B_y, 이동 횟수} - 각 상태에서 양쪽 수레가 독립적으로 상하좌우 움직임
→ 최대 16가지 경우 탐색 - 방문 체크는
boolean[N][M][2]형태로
각 수레가 방문한 칸을 저장 - 단, 두 수레의 동시 이동 + 교차 불가 등 제약 때문에
visited배열을 deep copy하여 상태마다 별도로 관리 - 두 수레 모두 도착지에 도달 시
answer갱신
코드
import java.util.*;
class Solution {
static int N, M;
static class Node{
int [] loc;
boolean [][][] visited;
public Node(int [] loc, boolean [][][] visited){
this.loc = loc;
this.visited = visited;
}
}
public int solution(int[][] maze) {
int answer = Integer.MAX_VALUE;
N = maze.length;
M = maze[0].length;
int [] end = new int [4];
int [] start = new int [4];
// 벽과 빈칸 빼고 정보 저장 후 전부 초기화
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
if(maze[i][j]==1){
start[0] = i;
start[1] = j;
}
else if(maze[i][j]==2){
start[2] = i;
start[3] = j;
}
else if(maze[i][j]==3){
end[0] = i;
end[1] = j;
}
else if(maze[i][j]==4){
end[2] = i;
end[3] = j;
}
if(maze[i][j]!=5){
maze[i][j] =0;
}
}
}
//BFS를 돌면서 이동
ArrayDeque<Node> q = new ArrayDeque<>();
boolean [][][] arr = new boolean[N][M][2];
arr[start[0]][start[1]][0] = true;
arr[start[2]][start[3]][1] = true;
q.add(new Node(new int[]{start[0], start[1], start[2],start[3], 0},arr ));
int [] dx = {1, 0, -1, 0};
int [] dy = {0, 1, 0, -1};
while(!q.isEmpty()){
Node now = q.poll();
int [] cur = now.loc;
int nowRX = cur[0];
int nowRY = cur[1];
int nowBX = cur[2];
int nowBY = cur[3];
int cnt = cur[4];
if(cnt>answer){
continue;
}
if(nowRX == end[0] && nowRY == end[1] && nowBX == end[2] && nowBY == end[3]){
answer = Math.min(answer, cnt);
continue;
}
boolean [] isDest = {true, true};
for(int i=0; i<4; i++){
int moveRX = nowRX;
int moveRY = nowRY;
if(nowRX != end[0] || nowRY != end[1]){
moveRX += dx[i];
moveRY += dy[i];
isDest[0] = false;
}
for(int j = 0; j<4; j++){
int moveBX = nowBX;
int moveBY = nowBY;
if(nowBX != end[2] || nowBY != end[3]){
moveBX += dx[j];
moveBY += dy[j];
isDest[1] = false;
}
// 서로 겹치지않고 이동이 가능하다면
if(canGo(moveRX, moveRY)&&canGo(moveBX, moveBY)
&& (moveRX!=moveBX ||moveRY!=moveBY)
&& ((moveRX!= nowBX || moveRY!= nowBY) || (moveBX!= nowRX || moveBY!=nowRY))
&& maze[moveRX][moveRY]!=5 && maze[moveBX][moveBY]!=5 ){
// 이미 자신의 도착칸에 도착했다면 이동할 수 없기에 visited 검사 X
if((!isDest[0] && now.visited[moveRX][moveRY][0])||(!isDest[1] && now.visited[moveBX][moveBY][1])){
continue;
}
boolean [][][] nowVisited = deepCopy(now.visited);
nowVisited[moveRX][moveRY][0] = true;
nowVisited[moveBX][moveBY][1] = true;
q.add(new Node(new int[]{moveRX, moveRY, moveBX, moveBY, cnt+1}, nowVisited));
}
}
}
}
return answer==Integer.MAX_VALUE? 0:answer;
}
static boolean canGo(int x, int y){
return x>=0&&y>=0&&x<N&&y<M;
}
static boolean [][][] deepCopy(boolean [][][] arr){
boolean [][][] temp = new boolean[N][M][2];
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
for(int k=0; k<2; k++){
temp[i][j][k] = arr[i][j][k];
}
}
}
return temp;
}
}반응형
'PS > 프로그래머스(Programmers)' 카테고리의 다른 글
| Lv.3 2차원 동전 뒤집기 [C++] (0) | 2026.03.01 |
|---|---|
| Lv.2 점프와 순간 이동 [C++] (2) | 2026.02.05 |
| Lv.2 피로도 [JAVA] (0) | 2025.09.10 |
| Lv.3 산 모양 타일링 [JAVA] (0) | 2025.09.05 |
| Lv.2 마법의 엘리베이터 [JAVA] (3) | 2025.08.26 |
