개발 지식/알고리즘

[백준] 1600 말이 되고픈 원숭이

트리맨스 2021. 6. 12. 23:47
반응형

 

문제를 읽어보고 오자.

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

 

1600번: 말이 되고픈 원숭이

첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있

www.acmicpc.net

 

문제를 읽어 보면 그래프 탐색을 사용하는 문제인 것을 알 수 있다. 하지만 약간 까다로운 점은, 특정 조건의 이동을 특정한 횟수 안에 실행한다는 점이다. 이것에 대한 모든 경우를 세야 할까?

 

나는 처음에 말처럼 움직인 횟수를 큐에 저장해서 확인해 보았다. 하지만 이러한 방법을 사용하니 방문한 경우에 대해서 오류가 있다는 것을 알게 되었다. 벽 부수기 문제 ( https://www.acmicpc.net/problem/2206 ) 처럼 한 개의 벽을 부수는 것처럼, 3차원 배열을 이용해야 함을 알게 되었다.

 

3차원 배열을 이용하여 말처럼 이동을 할 때, 다음 차원으로 넘어가야 정상적인 결과를 도출할 수 있다. 말처럼 n번 이동했을 경우에는, n번째 차원에서 생각해야지 서로 방해하지 않게 된다. 기본적인 탐색 방법은 BFS를 이용한다.

 

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
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
 
/*
dp로 풀이가 될까 했으나, 길이 보이지 않았음.
예전에 비슷한 문제를 풀이한 적이 있어서 참고했다. (백준 2206)
x,y,horse 의 3개 변수값을 가지고 있는 큐를 선언.
3차원 배열을 통해서 K + 1 개의 차원에서 bfs를 돌린다.
각각의 차원에서 알아서 탐색이 될 것이며, 가장 빨리 목표에 도달하는 곳이 정답일 것이다.
정답에 도달하지 못하면 while문을 빠져나와 -1을 반환하게 될 것이다.
*/
 
typedef struct
{
    int x, y, horse;
} loc;
 
int map[200][200];
int visited[200][200][30];
int K, W, H;
 
int bfs()
{
    queue<loc> q;
    int move_horse_x[8= {1221-1-2-2-1};
    int move_horse_y[8= {21-1-2-2-112};
    int move_x[4= {1-100};
    int move_y[4= {001-1};
    int ans = -1;
 
    visited[0][0][0= 1;
    q.push((loc){000});
    while (!q.empty())
    {
        loc a = q.front();
        q.pop();
        int x = a.x;
        int y = a.y;
        int horse = a.horse;
        if ((y == H - 1&& (x == W - 1))
            return (visited[y][x][horse] - 1);
        /* 일반적인 인접한 곳 이동 */
        for (int i = 0; i < 4; i++)
        {
            int dx = x + move_x[i];
            int dy = y + move_y[i];
            if (dx >= 0 && dx < W && dy >= 0 && dy < H && !map[dy][dx] && !visited[dy][dx][horse])
            {
                visited[dy][dx][horse] = visited[y][x][horse] + 1;
                q.push((loc){dx, dy, horse});
            }
        }
        /* 말처럼 이동 */
        for (int i = 0; i < 8; i++)
        {
            int dx = x + move_horse_x[i];
            int dy = y + move_horse_y[i];
            if (dx >= 0 && dx < W && dy >= 0 && dy < H && !map[dy][dx] && !visited[dy][dx][horse + 1&& horse < K)
            {
                visited[dy][dx][horse + 1= visited[y][x][horse] + 1;
                q.push((loc){dx, dy, horse + 1});
            }
        }
    }
    return (-1);
}
 
int main()
{
    //freopen("test", "r", stdin);
    cin >> K >> W >> H;
    for (int i = 0; i < H; i++)
        for (int j = 0; j < W; j++)
            cin >> map[i][j];
 
    cout << bfs();
    return (0);
}
cs

 

알고리즘의 세계는 끝이 없다. ㅠㅜ 나중에 한번 체계적으로 공부를 해봐야 할 것 같다.

 

반응형

'개발 지식 > 알고리즘' 카테고리의 다른 글

[백준] 1406 에디터  (0) 2021.06.21
[백준] 4963 섬의 개수  (0) 2021.06.19
[백준] 14719 빗물  (0) 2021.05.26
[백준] 2661 좋은 수열  (0) 2021.05.14
[백준] 1058 친구  (0) 2021.05.08