티스토리 뷰

 

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

 

17129번: 윌리암슨수액빨이딱따구리가 정보섬에 올라온 이유

첫째 줄에 정보섬 2층의 크기 n과 m이 주어진다. (1 ≤ n,m ≤ 3000, 4 ≤ n×m ≤ 9×106) 이후 n행 m열에 걸쳐 0, 1, 2, 3, 4, 5로만 구성된 Ai,j가 주어진다. Ai,j와 Ai,j+1사이에 공백은 주어지지 않는다. 2,

www.acmicpc.net

 

✨ 문제 풀이

2가 딱따구리 가족이므로 2의 (y, x)좌표가 시작점이 될 것입니다. 그리고 3, 4, 5는 딱따구리 가족이 각자 먹고 싶은 음식이고 종착점이 됩니다. 딱따구리 가족은 3, 4, 5 중 아무거나 하나만 가장 먼저 먹을 수 있는지만 구하면 됩니다. 1은 장애물이라 갈 수 없으며 0은 지나갈 수 있습니다. 딱따구리 가족은 한 번에 한 칸씩, 상하좌우 4방향으로만 움직일 수 있습니다.

 

n*m 모양의 격자 무늬 행렬을 BFS를 이용해 푸는 문제입니다. 아래 코드를 응용할게요.

https://shunnyjang.tistory.com/17

 

[c++] n*m 격자 무늬, 행렬 BFS 알고리즘 문제 코드

#BFS n행, m열의 행렬을 받고 상하좌우 4방향으로 한 칸씩 옮기면서 해답을 찾아가는 BFS 문제를 해결하기 위한 응용 코드입니다. 문제에서 주어진 조건을 잘 읽고 아래 코드를 응용해서 풀이하면

shunnyjang.tistory.com

 

🗓 코드

#include <iostream>
#include <queue>
#include <utility>

using namespace std;

#define MAXINT 3001

int n, m, start_y, start_x;
int dx[] = {0, -1, 0, 1};
int dy[] = {1, 0, -1, 0};

int map[MAXINT][MAXINT];
int dist[MAXINT][MAXINT];
queue<pair<int, int>> location;

void getInput()
{
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        char *temp = new char[m];
        scanf("%s", temp);
        for (int j = 0; j < m; j++)
        {
            map[i][j] = temp[j] - '0';
            if (map[i][j] == 2)
                start_y = i, start_x = j;
        }
    }
}

int solve()
{
    dist[start_y][start_x] = 0;
    location.push({start_y, start_x});
    while (!location.empty())
    {
        int y = location.front().first;
        int x = location.front().second;
        location.pop();

        // 3, 4, 5 중 하나에 도착하면 거리를 반환하고 종료
        if (map[y][x] > 2)
            return dist[y][x];

        for (int i = 0; i < 4; i++)
        {
            int ny = y + dy[i];
            int nx = x + dx[i];

            if (ny < 0 || nx < 0 || ny >= n || nx >= m)
                continue;
            // 장애물(1)이거나 방문한 적 있는 격자는 다음에 방문하지 않음
            if (map[ny][nx] == 1 || dist[ny][nx] > 0)
                continue;
            dist[ny][nx] = dist[y][x] + 1;
            location.push({ny, nx});
        }
    }
    // 3, 4, 5 중 아무것도 만나지 못하고 탐색 완전 종료
    return -1;
}

void getResult()
{
    int result = solve();
    if (result > 0)
        printf("TAK\n%d", result);
    else
        printf("NIE\n");
}

int main(int argc, char const *argv[])
{
    getInput();
    getResult();
    return 0;
}

 

이때 시작점은 2의 좌표, 종착점은 3 또는 4또는 5의 좌표가 될 것이고 몇 개의 0을 지나서 갈 수 있는지 구해야 합니다. 따라서 (y, x)에 도달하는 데 몇 개의 0을 지나서 올 수 있는지 거리를 저장하는 배열 dist[i][j]를 선언하겠습니다. dist에 0 이상의 값이 이미 있으면 방문했다는 표시와 같으니 visited는 dist로 대체합니다.

int dist[MAXINT][MAXINT]

장애물인 1을 만나면 방문할 좌표를 저장하는 큐에 저장하지 않습니다. 당연히 방문한 적 있는 좌표도 다시 방문하지 않기 때문에 dist[i][j] 값이 0보다 크면 큐에 저장하지 않습니다.

if (map[ny][nx] == 1 || dist[ny][nx] > 0)
                continue;

장애물이 아니고 갈 수 있는 위치라면 방문할 좌표로 큐에 저장합니다.

dist[ny][nx] = dist[y][x] + 1;
location.push({ny, nx});

이때 3, 4, 5 중 하나에 먼저 도착하게 되면 그 때 거리를 구하고 종료합니다.

if (map[y][x] > 2)
    return dist[y][x];

 

'Algorithm' 카테고리의 다른 글

[백준/c++] 2606 바이러스  (0) 2022.04.07
[백준/c++] 2638 치즈  (0) 2022.04.07
[c++] n*m 격자 무늬, 행렬 BFS 알고리즘 문제 코드  (0) 2022.04.07
Graph 알고리즘  (0) 2022.04.07
[프로그래머스/python] 입국심사  (0) 2022.03.26
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
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
글 보관함