알고리즘 풀이/프로그래머스
[level2] 프로그래머스 - 빛의 경로 사이클(JAVA)
데롱디롱
2021. 9. 20. 02:07
728x90
문제가 잘 이해가지 않아서,
질문하기에 문제 설명 보고나서 풀었다ㅠ
[ 문제 풀이 ]
- grid의 각 정점이 4방향 [상, 하, 좌, 우]로 들렸는지 여부를 저장할 3차 배열을 만들어준다.
- 방향(d)의 순서는 '시계 방향' 혹은 '반시계 방향'처럼 쭉 이어지게 정해야 나중에 방향 전환을 계산할 때 편하다.
나는 [ 아래, 왼, 위, 오른]의 순서로 정하고 dr, dc를 만들어주었다.
- 각 정점마다 모든 들리지 않은 방향에 대하여 빛의 경로를 구해준다. => light함수
- 방문 처리를 하면서, 들리지 않은 방향으로 나아가본다.
빛 S : 현재 방향을 유지
빛 L : 좌회전
빛 R : 우회전
회전 방법은 여러 가지가 있다.
본인의 d 순서에 맞게 잘 짜면 된다.
if (grid[r].charAt(c) == 'L') d = d == 0 ? 3 : d - 1; // 좌회전 else if (grid[r].charAt(c) == 'R') d = d == 3 ? 0 : d + 1; // 우회전
나는 위에처럼 짰지만, 이렇게도 될 것 같다.
if (grid[r].charAt(c) == 'L') d = (d + 3) % 4; // 좌회전 else if (grid[r].charAt(c) == 'R') d = (d + 1) % 4; // 우회전
그냥 d를 왼쪽, 오른쪽으로 회전시킬 수 있는 방법이라면 뭐든 가능!!!! ^0^
- d의 방향으로 또 한 칸 이동한다.
만약, ( r, c )가 배열 밖으로 나간 경우엔 반대편으로 이동시켜준다.
각 행과 열의 길이를 더한 다음에, 그 길이로 다시 나눈 나머지로 바꾸면
배열을 벗어나는 좌표에 대해 처리가 가능하다.
- 이동하며 거리를 증가시켰던 cnt를 answer(ArrayList)에 추가한다.
- answer을 오름차순으로 정렬한 뒤, int형 배열로 바꾸어 리턴한다.
[ 전체 코드 ]
import java.util.ArrayList;
class Solution {
static int R, C;
static int[] dr = { -1, 0, 1, 0 }, dc = { 0, -1, 0, 1 }; // 아래, 왼, 위, 오른
static boolean[][][] isVisited;
public int[] solution(String[] grid) {
ArrayList<Integer> answer = new ArrayList<Integer>();
R = grid.length;
C = grid[0].length();
isVisited = new boolean[R][C][4];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
for (int d = 0; d < 4; d++) {
if (!isVisited[i][j][d])
answer.add(light(grid, i, j, d ));
}
}
}
return answer.stream().sorted().mapToInt(i -> i).toArray();
}
private static int light(String[] grid, int r, int c, int d) {
int cnt = 0; // 이동거리
while (true) {
if (isVisited[r][c][d])
break;
cnt++; // 거리증가
isVisited[r][c][d] = true; // 방문처리
if (grid[r].charAt(c) == 'L')
d = d == 0 ? 3 : d - 1; // 좌회전
else if (grid[r].charAt(c) == 'R')
d = d == 3 ? 0 : d + 1; // 우회전
r = (r + dr[d] + R) % R;
c = (c + dc[d] + C) % C;
}
return cnt;
}
}
[ 케이스 공유 ]
만약 11번만 틀리신다면, 정렬을 한 후 리턴하는지 확인하시기 바랍니다!
옼ㅋㅋ 근데, 무려 14점이나 줬다... ^0^