백준 6087 레이저 통신
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 6087 레이저 통신

by KyeongMin 2019. 9. 19.
728x90
반응형

https://www.acmicpc.net/problem/6087

 

6087번: 레이저 통신

문제 크기가 1×1인 정사각형으로 나누어진 W×H 크기의 지도가 있다. 지도의 각 칸은 빈 칸이거나 벽이며, 두 칸은 'C'로 표시되어 있는 칸이다. 'C'로 표시되어 있는 두 칸을 레이저로 통신하기 위해서 설치해야 하는 거울 개수의 최솟값을 구하는 프로그램을 작성하시오. 레이저로 통신한다는 것은 두 칸을 레이저로 연결할 수 있음을 의미한다. 레이저는 C에서만 발사할 수 있고, 빈 칸에 거울('/', '\')을 설치해서 방향을 90도 회전시킬 수 있다. 

www.acmicpc.net

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
#include<stdio.h>
#include<string.h>
#include<queue>
#define NSIZE 100
#define MSIZE 100
using namespace std;
char input[NSIZE][MSIZE];
int chk[NSIZE][MSIZE];
int N, M;
int sy, sx,ey,ex;
int dy[] = {0,0,1,0,-1 };
int dx[] = {01,0,-1,0 };
void init() {
 
    scanf("%d %d"&M, &N);
    memset(chk, 0x32sizeof(chk));
    for (int i = 0; i < N; i++) {
        scanf(" %s", input[i]);
    }
    int c = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (input[i][j] == 'C'&&c==0) {
                sy = i;
                sx = j;
                c++;
            }
            else if (input[i][j] == 'C'&&== 1) {
                ey = i;
                ex = j;
                c++;
            }
        }
    }
}
struct Data {
    int y, x, cnt,dir;
};
void bfs() {
    queue<Data> q;
    q.push({ sy,sx,1,0});
    chk[sy][sx] = 1;
    while (!q.empty()) {
        Data c = q.front(); q.pop();
        for (int dir = 1; dir <= 4; dir++) {
            Data n;
            n.y = c.y + dy[dir];
            n.x = c.x + dx[dir];
            n.dir = c.dir;
            if (dir !=n.dir&&c.dir!=0) {
                n.cnt = c.cnt + 1;
                n.dir = dir;
            }
            else {
                n.cnt = c.cnt;
                n.dir = dir;
            }
            if (0 <= n.y&&n.y < N && 0 <= n.x&&n.x < M) {
                if (chk[n.y][n.x]>=n.cnt && input[n.y][n.x] != '*') {
                    chk[n.y][n.x] = n.cnt;
                    q.push(n);
                }
            }
 
        }
    }
}
void print() {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            printf("%2d", chk[i][j]);
        }
        printf("\n");
    }
}
int main(void) {
    init();
    bfs();
//    print();
    printf("%d", chk[ey][ex]-1);
    return 0;
}
 
 

이문제는 처음에 다들 그렇게 할지 모르겠지만 거울을 위치 시키고 그상태에서 연결이 가능한지에 대해서 

했었습니다. 하지만 그렇게 하면 시간적으로 초과가 걸리기 때문에 절대로 풀수 없습니다. 

그렇다면 어떤식으로 해결을 해야하는지 말을하자면 이렇습니다.

C 는 두개 이기때문에 우선 두개의    y 와 x값을 각각 저장합니다. 

그렇게 히고 나서  출발점인 y와 x  값을 정하고 그위치에서 bfs를 돌리되 이전에 dir과 같은면 cnt를 증가하지 않고

다르면 cnt를 증가하는데 대신 그값이 최소가 되도록 돌려주면됩니다. 

그렇게 하면  마지막 C에 몇번의 턴을 했는지가 저장하게 됩니다. 

정말 다시 생각해보면 쉽지 않나요?

여기서 포인트는 경로를 최소로 저장을 해야하기때문에 chk에 0x32 정도의 엄청 큰수로 초기화를 했고

저렇게 조건을 

이렇게 조건을 해서 뽑아내면 됩니다. 방법은 여러가지 있지만 거울을 모든경우에 놓고 하게되면 절대 풀 수 

없으니 그점만 주의해서 bfs를 돌리면 됩니다. 

오늘은 여기까지이고 다음은 다른문제로 찾아뵙겠습니다.

728x90
반응형

'알고리즘 모음집 > 알고리즘 (Algorithm)' 카테고리의 다른 글

백준 16509 장군  (0) 2019.09.21
백준 9328 열쇠  (0) 2019.09.19
백준 16918 봄버맨  (0) 2019.09.17
백준 9019 DSLR  (0) 2019.09.17
백준 2638 치즈  (0) 2019.09.17

댓글