알고리즘 풀이/프로그래머스

[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 )가 배열 밖으로 나간 경우엔 반대편으로 이동시켜준다.

각 행과 열의 길이를 더한 다음에, 그 길이로 다시 나눈 나머지로 바꾸면
배열을 벗어나는 좌표에 대해 처리가 가능하다.

 

- 이동하며 거리를 증가시켰던 cntanswer(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^