728x90
https://programmers.co.kr/learn/courses/30/lessons/60063
// 코드
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
|
import java.util.*;
class Solution {
// 좌표정보를 관리하는 클래스
class Point {
// 행, 열, 방향, 시간
int row, col, dir, time;
Point(int row, int col, int dir, int time) {
this.row = row;
this.col = col;
this.dir = dir;
this.time = time;
}
}
// 드론의 방향 : 시계방향으로..
static final int UP = 0;
static final int RIGHT = 1;
static final int DOWN = 2;
static final int LEFT = 3;
// 상, 하, 좌, 우
int[][] Deltas = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
// 0 시계, 1 반시계 돌림..
int[][][] RotateDeltas = {
{ {1, 1}, {1, -1}, {-1, -1}, {-1, 1} },
{ {1, -1}, {-1, -1}, {-1, 1}, {1, 1} }
};
int[][][] CornerDeltas = {
{ {-1, 1}, {1, 1}, {1, -1}, {-1, -1} },
{ {-1, -1}, {-1, 1}, {1, 1}, {1, -1} }
};
// 일반 멤버 변수
int N;
int[][] Board;
Deque<Point[]> DEQ = new ArrayDeque<>();
boolean[][][] Visited = new boolean[100][100][4];
boolean isValid(Point[] pt) {
for(int i = 0; i < 2; ++i) {
// 범위를 벗어나는 경우
if(pt[i].row < 0 || pt[i].row > N-1 || pt[i].col < 0 || pt[i].col > N-1) return false;
// 벽인경우
if(Board[pt[i].row][pt[i].col] == 1) return false;
// 방문한경우
if(Visited[pt[i].row][pt[i].col][pt[i].dir]) return false;
}
return true;
}
// 파라미터 정보 : (현재 위치 정보, 시계방향인지 반시계방향인지, 회전축)
int rotate(Point[] curr, int ccw, int idx) {
Point[] newPt = new Point[2];
// a회전축
int a = idx, b = (idx + 1) % 2;
int dir = curr[a].dir;
// 시계방향 1, 반시계방향 3
newPt[0] = new Point(
curr[a].row,
curr[a].col,
((curr[a].dir + (ccw == 0 ? 1 : 3)) % 4),
(curr[a].time + 1)
);
// 회전축이 아닌 나머지칸 즉 b를 기준으로 이동
newPt[1] = new Point(
curr[b].row + RotateDeltas[ccw][dir][0],
curr[b].col + RotateDeltas[ccw][dir][1],
((curr[b].dir + (ccw == 0 ? 1 : 3)) % 4),
(curr[a].time + 1)
);
// 회전 불가능한 경우
if(!isValid(newPt)) return 0;
if(Board[ curr[a].row + CornerDeltas[ccw][dir][0] ][ curr[a].col + CornerDeltas[ccw][dir][1] ] == 1) return 0;
for(int i = 0; i < 2; ++i) {
// 목적지 도달
if(newPt[0].row == N - 1 && newPt[0].col == N - 1) return newPt[i].time;
Visited[newPt[i].row][newPt[i].col][newPt[i].dir] = true;
}
DEQ.add( new Point[]{ newPt[0], newPt[1]} );
return 0;
}
// 메인 클래스
public int solution(int[][] board) {
Board = board;
N = board.length;
DEQ.add( new Point[]{ new Point(0, 0, RIGHT, 0), new Point(0, 1, LEFT, 0) } );
Visited[0][0][RIGHT] = true;
Visited[0][1][LEFT] = true;
Point[] curr = new Point[2];
Point[] newPt = new Point[2];
while( (curr = DEQ.poll()) != null ) {
for(int j = 0; j < 4; ++j) { // 4방 탐색
for(int i = 0; i < 2; ++i) { // 이동할 곳 : 두 개의 새로운 좌표를 만들어낸다.
newPt[i] = new Point( (curr[i].row + Deltas[j][0]), (curr[i].col + Deltas[j][1]), curr[i].dir, (curr[i].time + 1));
}
// 유효한 경우만 추가
if(!isValid(newPt)) continue;
for(int i = 0; i < 2; ++i) {
// 목적지 도착 확인
if(newPt[i].row == N-1 && newPt[i].col == N-1) return newPt[i].time;
Visited[newPt[i].row][newPt[i].col][newPt[i].dir] = true;
}
DEQ.add(new Point[]{ newPt[0], newPt[1] });
}
// 회전 : 시계방향 0(ccw), 반시계방향 1(ccw)
for(int ccw = 0; ccw < 2; ++ccw) {
for(int i = 0; i < 2; ++i) {
// i = 0 이면 첫 번째칸을 축으로 회전
// i = 1 이면 두 번째칸을 축으로 회전
int ret = rotate(curr, ccw, i);
if(ret != 0 ) return ret;
}
}
}
// 문제조건상 이곳은 오지 못함.
// 아무값이나 반환
return 0;
}
}
|
cs |
반응형
'CS > 알고리즘_KAKAO BLIND RECRUITMENT' 카테고리의 다른 글
2021 KAKAO BLIND RECRUITMENT : 매출 하락 최소화 (0) | 2021.10.26 |
---|---|
2021 KAKAO BLIND RECRUITMENT : 순위 검색(비트마스크 & 집합) (0) | 2021.10.25 |
2021 KAKAO BLIND RECRUITMENT : 합승 택시 요금(플로이드 워셜) (0) | 2021.10.20 |
2019 KAKAO BLIND RECRUITMENT : 실패율 (0) | 2021.10.19 |
2020 KAKAO BLIND RECRUITMENT : 가사 검색 (0) | 2021.10.18 |