백준 16137 견우와 직녀
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

백준 16137 견우와 직녀

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

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

 

16137번: 견우와 직녀

첫째 줄에 지형의 행과 열의 크기를 나타내는 정수 N (2 ≤ N ≤ 10)과 새로 만들어지는 오작교의 주기를 의미하는 정수 M(2 ≤ M ≤ 20)이 주어진다. 다음 N개의 줄에는 줄마다 배열의 각 행을 나타내는 N개의 정수가 한 개의 빈칸을 사이에 두고 주어진다. 각 칸에 들어가는 값은 0 이상 20 이하이다. 또한, 각 칸에 들어가는 정수의 의미는 다음과 같다. 1: 이동할 수 있는 일반적인 땅 0: 건널 수 없는 절벽 2 이상의 수: 적혀있는 수

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include<stdio.h>
#include<queue>
#include<string.h>
#define NSIZE 10
#define MSIZE 20
using namespace std;
int N, M;
int input[NSIZE][NSIZE];
int chk[NSIZE][NSIZE];
int dy[] = { 0,1,0,-1 };
int dx[] = { 1,0,-1,0 };
int ret = 0;
int Min = 0x7fffffff;
struct Data {
    int y, x, cnt, time;
};
void init() {
    scanf("%d %d"&N, &M);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            scanf("%d"&input[i][j]);
        }
    }
}
bool chkHole(int y,int x) {
    int cnt = 0;
    for (int dir = 0; dir < 4; dir++) {
        int ny = y+dy[dir]; int nx = x+dx[dir];
        int nny = y+dy[(dir+1)%4]; int nnx = x+dx[(dir + 1) % 4];
 
        if (0 <= ny && ny < N && 0 <= nx && nx < N&& 0 <= nny && nny < N && 0 <= nnx && nnx < N) {
            if (input[ny][nx] == 0 && input[nny][nnx] == 0return false;
        }
    }
    return true;
}
void bfs() {
    queue<Data>q;
    memset(chk, 0x32sizeof(chk));
    q.push({ 0,0,0,0 });
    chk[0][0= 1;
    while (!q.empty()) {
        Data c = q.front(); q.pop();
        if (c.y == N - 1 && c.x == N - 1) {
            ret = chk[c.y][c.x];
            return;
        }
        for (int dir = 0; dir < 4; dir++) {
            Data n;
            n.y = c.y + dy[dir];
            n.x = c.x + dx[dir];
            n.cnt = c.cnt+1;
            n.time = c.time;
            if (0 <= n.y && n.y < N && 0 <= n.x && n.x < N) {
                if (chk[n.y][n.x]>=n.cnt && input[n.y][n.x] >= 1) {
                    if (input[n.y][n.x] >= 2&&n.time==0) {
                        if ( n.cnt%input[n.y][n.x] == 0) {
                            chk[n.y][n.x] = n.cnt;
                            n.time = 1;
                            q.push(n);
                        }
                        else {
                            n.cnt = n.cnt + (input[n.y][n.x]-(n.cnt % input[n.y][n.x]));
                            chk[n.y][n.x] = n.cnt;
                            n.time = 1;
                            q.push(n);
                        }
                    }
                    else if(input[n.y][n.x]==1) {
                        if (n.time == 1)n.time = 0;
                        chk[n.y][n.x] = n.cnt;
                        q.push(n);
 
                    }
                }
            }
        }
    }
}
void meeting() {
    ret = 0x7fffffff;
    bfs();
    if (Min > ret)Min = ret;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (input[i][j] == 0 && chkHole(i, j)) {
                input[i][j] = M;
                ret = 0x7fffffff;
                bfs();
                if (Min > ret)Min = ret;
                input[i][j] = 0;
            }
        }
    }
}
int main(void) {
    init();
    meeting();
    printf("%d\n", Min);
    return 0;
}
 
 

1번 견우와 직녀 알고리즘 포인트는 우선 최소로 거리가 가도록 해야하기때문에 약간 다엑스트라 방식을 적용해야하고

2번 오작교는 1초되면 사라지기때문에 두번 연속 못 건너가게하는 변수 하나 더 선언하고 

 

3 번오작교에 도달했을때 오작교생성 시간 계산해서 큐에 넣어주기만 하면 됩니다.

 

사실 1 번 2 번 방식은 진짜 쉽다고 생각할 수 있습니다. 1번은 그냥 체크배열을 가장 큰값으로 초기화하고 

간시간보다 작으면 다시 그거리를 큐에 넣으면 되기 때문에 쉽게 구현 가능하고 

2번은  변수에 오작교를 일단 갔으면 1로 체크를 해주고 그렇지 않으면 오작교를 건너는 식으로 구현하면됩니다.

이걸 보면 n.time 이라는 변수에 1로 오작교 건넜음을 체크해주면됩니다. 

하지만 다시 오작교가 아닌 거리에 오면 0으로 만들어줘야함을 잊지마세요.

 

이제 마지막으로 3번은 

소스를 보시면 

이건데 왜 저렇게 되냐 말씀드리면 이렇습니다. 

이해가 안되실 수 있는데 이해가 되셨으면 좋겠습니다. 저렇게 하면 답이 통과가 되더라구요

오늘도 여기까지이고 즐거운 코딩하세요.

728x90
반응형

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

백준 2065 나룻배  (0) 2019.10.02
백준 2931 가스관  (0) 2019.10.02
백준 4577 소코반  (0) 2019.09.30
백준 1260 DFS와 BFS  (0) 2019.09.29
백준 15662 톱니바퀴(2)  (0) 2019.09.29

댓글