[백준 1938번] 통나무 옮기기

2023. 4. 4. 01:09·알고리즘 문제풀이/백준
반응형

문제 링크: https://www.acmicpc.net/problem/1938

 

1938번: 통나무 옮기기

첫째 줄에 주어진 평지의 한 변의 길이 N이 주어진다. (4 ≤ N ≤ 50) 주어진다. 이어서 그 지형의 정보가 0, 1, B, E로 이루어진 문자열로 주어진다. 한 줄에 입력되는 문자열의 길이는 N이며 입력 문

www.acmicpc.net

<문제 풀이> BFS 알고리즘

 

이 문제는 통나무의 중심 좌표를 가지고 목적지까지 최단거리로 이동하는 BFS를 구현하면 됩니다.

 

통나무는 현재 자신이 있는 좌표에서 BFS로 다음 좌표로 이동할 때 아래 두 가지 동작을 합니다.

1. 현재 좌표에 있는 통나무의 방향을 유지한 채로 4방향으로 이동한다.

2. 현재 좌표에 있는 통나무를 회전한 상태로 다음 좌표로 이동한다.

 

통나무의 중심 좌표를 (x,y)라고 할 때 수평 방향 통나무, 수직 방향 통나무 각각을 아래와 같이 표현할 수 있습니다.

수평 방향 통나무 (x, y - 1) (x, y) (x, y + 1)
수직 방향 통나무 (x -1, y) (x, y) (x + 1, y)

 

다음 좌표로 이동할 때 위 세 좌표가 '1'을 만나는지, 배열을 벗어나는지 판단해 주면 됩니다.

회전할 때는 중심 좌표를 기준으로 8방향을 확인하면 됩니다.

 

방문 체크는 (x, y)의 좌표를 수평 또는 수직 방향으로 방문했는지 판단하기 위해서 3차원 배열을 사용합니다.

visited[x][y][k]

=> (x, y)의 좌표를 k 방향 통나무를 가지고 방문한 적이 있는가?

=> k =0 이면 수평 방향, k = 1이면 수직 방향입니다.

 

 

<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
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <queue>
using namespace std;
 
#define X first
#define Y second
 
class Bar {
public:
    int x, y, state;
    void setBar(int x, int y, int state) {
        this->x = x;
        this->y = y;
        this->state = state;
    }
    bool operator==(const Bar &bar) {
        if (this->x == bar.x && this->y == bar.y && this->state == bar.state) return true;
        else return false;
    }
};
 
Bar start, dest;
 
char board[50][50];
int visited[50][50][2]; // [i][j][0] = 수평, [i][j][1] = 수직, Bar의 가운데 좌표를 기준으로 방문체크
int n;
const int dx[4] = {0, 0, 1, -1};
const int dy[4] = {1, -1, 0, 0};
 
// Bar의 수평(0), 수직(1) 상태 리턴
int getState(vector<pair<int, int > > bar) {
    if (bar[0].X - bar[1].X == 0) return 0; //연속된 2개의 B의 X 좌표가 같으면 수평
    else return 1; // 그렇지 않으면 수직
}
 
void init() {
    for (int i = 0; i < 50; i++) {
        for (int j = 0; j < 50; j++) {
            for(int k=0; k<2; k++){
                visited[i][j][k] = -1;
            }
        }
    }
}
 
bool check(int x, int y) {
    return !(x < 0 || y < 0 || x >= n || y >= n || board[x][y] == '1');
}
 
void bfs() {
    queue<Bar> Q;
    Q.push({ start.x, start.y, start.state });
    visited[start.x][start.y][start.state] = 0;
 
    while (!Q.empty()) {
        auto cur = Q.front(); Q.pop();
        if (cur == dest) {
            return;
        }
        if (cur.state == 0) { // 수평으로 이동
            for (int dir = 0; dir < 4; dir++) { // 4방향 이동
                int nx = cur.x + dx[dir];
                int ny = cur.y + dy[dir];
                if (!check(nx, ny - 1) || !check(nx, ny) || !check(nx, ny + 1) || visited[nx][ny][cur.state] != -1) continue;
                Q.push({ nx, ny, cur.state });
                visited[nx][ny][cur.state] = visited[cur.x][cur.y][cur.state] + 1;
            }
            //수직방향으로 회전
            if (!check(cur.x - 1, cur.y) || !check(cur.x, cur.y) || !check(cur.x + 1, cur.y) || visited[cur.x][cur.y][!cur.state] != -1) continue;
            if (!check(cur.x - 1, cur.y - 1) || !check(cur.x - 1, cur.y + 1) || !check(cur.x + 1, cur.y - 1) || !check(cur.x + 1, cur.y + 1))continue;
            Q.push({ cur.x, cur.y, !cur.state });
            visited[cur.x][cur.y][!cur.state] = visited[cur.x][cur.y][cur.state] + 1;
 
        }
        else { // 수직으로 이동
            for (int dir = 0; dir < 4; dir++) { // 4방향 이동
                int nx = cur.x + dx[dir];
                int ny = cur.y + dy[dir];
                if (!check(nx - 1, ny) || !check(nx, ny) || !check(nx + 1, ny) || visited[nx][ny][cur.state] != -1) continue;
                Q.push({ nx, ny, cur.state });
                visited[nx][ny][cur.state] = visited[cur.x][cur.y][cur.state] + 1;
            }
            //수평방향으로 회전
            if (!check(cur.x, cur.y - 1) || !check(cur.x, cur.y) || !check(cur.x, cur.y + 1) || visited[cur.x][cur.y][!cur.state] != -1) continue;
            if (!check(cur.x - 1, cur.y - 1) || !check(cur.x - 1, cur.y + 1) || !check(cur.x + 1, cur.y - 1) || !check(cur.x + 1, cur.y + 1))continue;
            Q.push({ cur.x, cur.y, !cur.state });
            visited[cur.x][cur.y][!cur.state] = visited[cur.x][cur.y][cur.state] + 1;
        }
    }
}
 
void input() {
    cin >> n;
    vector<pair<int, int> > S, E;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> board[i][j];
            if (board[i][j] == 'B') S.push_back({ i, j });
            else if (board[i][j] == 'E')E.push_back({ i, j });
        }
    }
    start.setBar(S[1].X, S[1].Y, getState(S));
    dest.setBar(E[1].X, E[1].Y, getState(E));
}
void solve() {
    init();
    input();
    bfs();
    int ans = visited[dest.x][dest.y][dest.state];
    if (ans == -1) cout << '0';
    else cout << ans;
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
 
    solve();
 
    return 0;
}
Colored by Color Scripter
cs
 

 

반응형
저작자표시 (새창열림)

'알고리즘 문제풀이 > 백준' 카테고리의 다른 글

[백준 21608번] 상어 초등학교  (0) 2023.04.08
[백준 23289번] 온풍기 안녕!  (0) 2023.04.06
[백준 9944번] NxM 보드 완주하기  (0) 2023.04.01
[백준 23290번] 마법사 상어와 복제  (0) 2023.03.30
[백준 17135번] 캐슬 디펜스  (0) 2023.03.28
'알고리즘 문제풀이/백준' 카테고리의 다른 글
  • [백준 21608번] 상어 초등학교
  • [백준 23289번] 온풍기 안녕!
  • [백준 9944번] NxM 보드 완주하기
  • [백준 23290번] 마법사 상어와 복제
슥지니
슥지니
개발 블로그
  • 슥지니
    슥지니의 코딩노트
    슥지니
  • 전체
    오늘
    어제
    • 분류 전체보기 (198)
      • 알고리즘 문제풀이 (158)
        • 백준 (158)
      • 알고리즘 (6)
      • Node.js (2)
        • MongoDB (1)
        • 기타 (1)
      • spring (0)
      • 가상화폐 (1)
        • 바이낸스(Binance) (1)
      • C++ 테트리스 게임 (0)
      • C++ (10)
      • 안드로이드 프로그래밍 (21)
        • 코틀린 (21)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    BFS
    다이나믹 프로그래밍
    dfs
    코틀린을 활용한 안드로이드 프로그래밍
    구현
    우선순위 큐
    C++
    그리디
    콘솔 테트리스 게임
    자료구조
    알고리즘
    코틀린
    dp
    백트랙킹
    Kotlin
    콘솔
    시뮬레이션
    그래프
    C
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
슥지니
[백준 1938번] 통나무 옮기기
상단으로

티스토리툴바