ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 2344번 거울
    문제 풀이 2020. 7. 18. 22:07

    2344번 거울


    문제


    세로 N, 가로 M 크기의 상자가 있다. 이 상자 안에는 몇 개의 거울이 들어 있다. 상자를 위에서 봤을 때, 거울은 한 칸 안에 대각선 모양으로 들어있다고 한다. 또, 상자의 테두리를 따라서 칸마다 구멍이 뚫려 있다. 편의상 구멍은 왼쪽 위에 뚫려있는 것부터 시계 반대 방향으로 1, 2, …, 2N+2M 의 번호가 붙어 있다. 예를 들어 다음과 같은 경우를 보자.

    이제 이 상자에 뚫려있는 구멍으로 빛을 쏜다고 생각해보자. 1번 구멍으로 쏠 경우에는 (1, 2)의 위치에 있는 거울에 반사되어 9번 구멍으로 빛이 가게 된다. 또, 2번 구멍으로 빛을 쏠 경우에는 (2, 2)의 위치에 있는 거울과 (1, 2)에 있는 거울에 차례로 반사되어 7번 구멍으로 빛이 나가게 된다.

    이와 같이 상자의 모양이 주어졌을 때, 각 구멍으로 쏜 빛이 나가게 되는 구멍을 구하는 프로그램을 작성하시오.


    입력


    첫째 줄에 N, M (1 ≤ N, M ≤ 1,000)이 주어진다. 다음 N개의 줄에는 M개의 수로 상자의 모양이 주어진다. 거울이 있는 위치는 1로, 거울이 없는 위치는 0으로 주어진다. 거울은 / 모양으로만 놓일 수 있다고 하자.


    출력


    첫째 줄부터 차례로 1번 구멍으로 쏜 빛이 나가는 구멍의 번호, 2번 구멍으로 쏜 빛이 나가는 구멍의 번호, …, 2N+2M번 구멍으로 쏜 빛이 나가는 구멍의 번호를 출력한다.




    풀이)

    재귀 방법을 이용해 빛이 어떤 구멍으로 나가는 지 확인해준 문제이다.


    1. 세로 N, 가로 M인 상자가 있다면 전체 map크기를 아래처럼 생각한다.

       (예시) N = 5, M =4 일경우

    맵 크기는 (N+2 =7) * (M+2 = 6)



    2. 구멍의 번호를 저장해준다. 

       (이 때, 거울의 위치와 1번 구멍을 햇갈리지 않기 위해 거울 있는 곳은 -1로 바꿔준다)

    3. 각 1번 구멍부터 출발해 다른 구멍의 번호(1이상)가 나올 때까지 탐색해준다.

     3.1 거울을 만날 경우 방향을 바꾼 뒤 탐색

    (방향은 항상 수직으로 바뀌며, 왼쪽 방향이였을 경우 위쪽 방향으로. 위쪽 방향이었을 경우 오른쪽 방향으로 바뀜.

     아래 그림처럼 바뀜)



     3.2 거울이 아닌 경우는 방향을 그대로 유지한 채 탐색



    코드)

    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
    #include <stdio.h>
    using namespace std;
     
    int N, M;
    int map[1005][1005];
    int dy[4= { -1,1,0,0 };
    int dx[4= { 0,0,-1,1 };
     
    int change_dir(int d) {
        if (d == 0return 3;
        else if (d == 1return 2;
        else if (d == 2return 1;
        else return 0;
    }
     
    int dfs(int y, int x,int dir) {
        int ny = y + dy[dir];
        int nx = x + dx[dir];
        //다른 구멍으로 빛이 빠짐
        if (map[ny][nx] >= 1return map[ny][nx];
        else {
            //거울을 만나면
            if (map[ny][nx] == -1return dfs(ny, nx, change_dir(dir));
            else //거울 안만나면 계속 빛 방향 유지
                return dfs(ny, nx, dir);
        }
    }
     
    int main() {
        scanf("%d %d"&N, &M);
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= M; j++) {
                scanf("%d"&map[i][j]);
                if (map[i][j] == 1) map[i][j] = -1;
            }
        }
        //1. 구멍 번호 채우기
        //왼쪽면, 오른쪽면 구멍 번호
        for (int i = 1; i <= N; i++) {
            map[i][0= i;
            map[N + 1 - i][M + 1= N + M + i;
        }
        //아래면, 윗면 구멍 번호
        for (int i = 1; i <= M; i++) {
            map[N + 1][i] = N + i;
            map[0][M + 1 - i] = N * 2 + M + i;
        }
     
        //2. 구멍에서 빛 쏘기
        //1) 왼쪽면 구멍에서
        for (int i = 1; i <= N; i++) {
            printf("%d ", dfs(i, 03));
        }
        //2) 아랫면 구멍에서
        for (int i = 1; i <= M; i++) {
            printf("%d ", dfs(N+1, i, 0));
        }
        //3) 오른쪽면, 빛 방향 : 왼쪽
        for (int i = N; i >= 1; i--) {
            printf("%d ", dfs(i, M+12));
        }
        //4) 위쪽면, 빛 방향 : 아래
        for (int i = M; i >= 1; i--) {
            printf("%d ", dfs(0, i, 1));
        }
        return 0;
    }
    cs


    '문제 풀이' 카테고리의 다른 글

    [백준] 11060번 점프점프  (0) 2020.07.22
    [백준] 2745번 진법 변환, 11005번 진법 변환 2  (0) 2020.07.20
    [백준] 2151번 거울설치  (0) 2020.07.17
    [백준] 1016번 제곱 ㄴㄴ수  (0) 2020.07.16
    [백준] 13901번 로봇  (0) 2020.07.15

    댓글

Designed by Tistory.