반응형
05-15 00:00
Today
Total
«   2024/05   »
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
관리 메뉴

개발하는 고라니

[백준] 3709번 : 레이저빔은 어디로 본문

Programming/백준

[백준] 3709번 : 레이저빔은 어디로

조용한고라니 2021. 5. 13. 01:10
반응형
 

3709번: 레이저빔은 어디로

레이저박스라는 게임은 정사각형  모양의 n x n 보드에서 진행한다. (체스판을 상상하면 된다) 레이저박스의 임의의 칸마다 우향우 거울이라는 장치가 설치되어 있고, 마지막으로 레이저 한개가

www.acmicpc.net


[DFS]

N x N 격자의 밖에서 레이저빔을 쐈을 때 우향우 거울을 통해 반사되어 최종적으로 레이저빔이 도착한 위치를 찾는 문제.

레이저 빔은 이미 지나온 곳도 다시 지날 수 있다. 그렇다고 해서 방문을 했는지 여부를 체크하지 않으면 안된다. 문제에서 주어진 것을 보면 알 수 있듯, 레이저빔이 격자 밖을 빠져나가지 못하면 0 0을 출력하라고 한 것을 보아 방문을 체크하지 않는다면 무한루프에 빠져 Stackoverflow 에러가 발생할 것이다. 그러면 어떻게 방문 체크를 하는가? 이미 지나온 정점을 다시 방문할 수 있어야 하고, 방문을 체크하는 방법.

 

그 방법은 여러 개가 존재하겠으나, 나는 방향(상하좌우)을 추가하여 한 정점에 최대 4번 방문할 수 있게 하였다.  그리고 우향우 거울은 들어온 방향에 관계없이 무조건 오른쪽으로 레이저빔을 틀어주므로 상 -> 우 -> 하 -> 좌 -> 상 -> ...이런 식으로 계속 갈 것이다. 따라서 방향에 인덱스를 부여하고 % 4 연산을 통해 오른쪽으로 틀어주는 것을 구현하도록 한다.

# Code </>

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    static int n, endY, endX;
    static int[] Y = {-1, 0, 1, 0}, X = {0, 1, 0, -1}; //상 -> 우 -> 하 -> 좌
    static boolean[][][] visit;
    static int[][] map;

    static void init(){
        for(int i=0; i<=n+1; i++){
            map[0][i] = -1; map[n+1][i] = -1;
            map[i][0] = -1; map[i][n+1] = -1;
        }
    }

    static void DFS(int y, int x, int dir) {
        if(map[y][x] < 0){
            endY = y;
            endX = x;
            return;
        }
        if(visit[y][x][dir]) {
            endY = 0;
            endX = 0;
            return;
        }

        visit[y][x][dir] = true;
        
        if(map[y][x] == 1) //우향우 거울(1)이면 우로 회전
            dir = (dir + 1) % 4;

        int ny = y + Y[dir];
        int nx = x + X[dir];

        DFS(ny, nx, dir);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(br.readLine());

        for(int a=0; a<t; a++){

            StringTokenizer st = new StringTokenizer(br.readLine());
            n = Integer.parseInt(st.nextToken());
            int r = Integer.parseInt(st.nextToken());

            endX = -1;
            endY = -1;
            int dir = -1; //방향(상,하,좌,우)
            map = new int[52][52];
            visit = new boolean[52][52][4];
            init();

            /* 우향우 거울 좌표 */
            for(int i=0; i<r; i++){
                st = new StringTokenizer(br.readLine());

                int y = Integer.parseInt(st.nextToken());
                int x = Integer.parseInt(st.nextToken());

                map[y][x] = 1;
            }
            /* 레이저 빔 좌표 */
            st = new StringTokenizer(br.readLine());

            int y = Integer.parseInt(st.nextToken());
            int x = Integer.parseInt(st.nextToken());

            if(x == n+1)     dir = 3; //좌
            else if(y == n+1)dir = 0; //상
            else if(x == 0)  dir = 1; //우
            else             dir = 2; //하

            DFS(y+Y[dir], x+X[dir], dir);

            System.out.println(endY + " " + endX);
        }
    }
}
반응형

'Programming > 백준' 카테고리의 다른 글

[백준] 4803번 : 트리  (0) 2021.05.26
[백준] 18405번 : 경쟁적 전염  (0) 2021.05.26
[백준] 5430번 : AC  (0) 2021.05.12
[백준] 5884번 : 감시 카메라  (0) 2021.05.11
[백준] 16441번 : 아기돼지와 늑대  (0) 2021.05.10
Comments