Post

[코딩테스트] 23/12/08 - 리코쳇 로봇 (Level2)

🌜 프로그래머스 링크

문제 설명

리코쳇 로봇이라는 보드게임이 있습니다.

이 보드게임은 격자모양 게임판 위에서 말을 움직이는 게임으로, 시작 위치에서 목표 위치까지 최소 몇 번만에 도달할 수 있는지 말하는 게임입니다.

이 게임에서 말의 움직임은 상, 하, 좌, 우 4방향 중 하나를 선택해서 게임판 위의 장애물이나 맨 끝에 부딪힐 때까지 미끄러져 이동하는 것을 한 번의 이동으로 칩니다.

다음은 보드게임판을 나타낸 예시입니다.

1
2
3
4
5
...D..R
.D.G...
....D.D
D....D.
..D....

여기서 “.”은 빈 공간을, “R”은 로봇의 처음 위치를, “D”는 장애물의 위치를, “G”는 목표지점을 나타냅니다. 위 예시에서는 “R” 위치에서 아래, 왼쪽, 위, 왼쪽, 아래, 오른쪽, 위 순서로 움직이면 7번 만에 “G” 위치에 멈춰 설 수 있으며, 이것이 최소 움직임 중 하나입니다.

게임판의 상태를 나타내는 문자열 배열 board가 주어졌을 때, 말이 목표위치에 도달하는데 최소 몇 번 이동해야 하는지 return 하는 solution함수를 완성하세요. 만약 목표위치에 도달할 수 없다면 -1을 return 해주세요.

제한사항

  • 3 ≤ board의 길이 ≤ 100
    • 3 ≤ board의 원소의 길이 ≤ 100
    • board의 원소의 길이는 모두 동일합니다.
    • 문자열은 “.”, “D”, “R”, “G”로만 구성되어 있으며 각각 빈 공간, 장애물, 로봇의 처음 위치, 목표 지점을 나타냅니다.
    • “R”과 “G”는 한 번씩 등장합니다.

문제풀이

  • 보드의 장애물과 시작위치 골인위치를 분석한다.
  • BFS를 사용하여 가장 빨리 도달할수있는경로를 탐색한다.
  • 미끄러지는 조건떄문에 방향아래에 while문을 사용하여 장애물이나 더갈수없을때까지 이동한다.
  • 이동횟수를 좌표마다 저장하고 방문기록을 남긴다.
  • 골인지점에 도달할경우 현재 좌표의 이동횟수를 반환하고 모두탐색한다.
  • 골인지점에 도달할수없으면 -1을반환한다.

Github 링크

참고할 문서

BFS-DFS

코드 (C++)

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
bool AbleToMove(int x, int y, vector<string>& board)
{
    return x < board.size() && y < board[x].size() && board[x][y] != 'D';  
}
int BFS(vector<string> board, int n, int m, int dx[], int dy[], Pos startPos, Pos endPos)
{
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    queue<Pos> q;
    q.push(startPos);
    visited[startPos.x][startPos.y] = true;
    while (!q.empty())
    {
        Pos cur = q.front();
        q.pop();
        if (cur.x == endPos.x && cur.y == endPos.y)
            return cur.dist;
        
        for (int i = 0; i < 4; ++i) {
            int nx = cur.x;
            int ny = cur.y;
            while (AbleToMove(nx + dx[i], ny + dy[i], board))
            {
                nx = nx + dx[i];
                ny = ny + dy[i];
            }
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny] && board[nx][ny] != 'D') {
                visited[nx][ny] = true;
                q.push({nx, ny, cur.dist + 1});
            }
        }
        
    }
    return -1;
}

int solution(vector<string> board) {
    int n = board.size();
    int m = board[0].size();
    int dx[] = {0, 0, 1, -1};
    int dy[] = {1, -1, 0, 0};
    
    Pos startPos;
    Pos endPos;
    bool isFoundStartPos = false;
    bool isFoundEndPos = false;
    for (int i = 0; i < board.size(); ++i)
    {
        for (int j = 0; j < m; ++j) {
            if (board[i][j] == 'R') {
                startPos.x = i;
                startPos.y = j;
                isFoundStartPos = true;
            } else if (board[i][j] == 'G') {
                endPos.x = i;
                endPos.y = j;
                isFoundEndPos = true;
            }
            if (isFoundEndPos && isFoundStartPos)
            {
                break;
            }
        }
    }
    return BFS(board, n, m, dx, dy, startPos, endPos);
}

##

This post is licensed under CC BY 4.0 by the author.