πŸ• Baaaaaarking/0x09κ°• - BFS

[BOJ G4][C++] λ°±μ€€ 2206번 : λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°

선달 2022. 4. 13. 18:05
λ°˜μ‘ν˜•

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

 

2206번: λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°

N×M의 ν–‰λ ¬λ‘œ ν‘œν˜„λ˜λŠ” 맡이 μžˆλ‹€. λ§΅μ—μ„œ 0은 이동할 수 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚΄κ³ , 1은 이동할 수 μ—†λŠ” 벽이 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚Έλ‹€. 당신은 (1, 1)μ—μ„œ (N, M)의 μœ„μΉ˜κΉŒμ§€ μ΄λ™ν•˜λ € ν•˜λŠ”λ°, μ΄λ•Œ μ΅œλ‹¨ 경둜

www.acmicpc.net

 

문제

N×M의 ν–‰λ ¬λ‘œ ν‘œν˜„λ˜λŠ” 맡이 μžˆλ‹€. λ§΅μ—μ„œ 0은 이동할 수 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚΄κ³ , 1은 이동할 수 μ—†λŠ” 벽이 μžˆλŠ” 곳을 λ‚˜νƒ€λ‚Έλ‹€. 당신은 (1, 1)μ—μ„œ (N, M)의 μœ„μΉ˜κΉŒμ§€ μ΄λ™ν•˜λ € ν•˜λŠ”λ°, μ΄λ•Œ μ΅œλ‹¨ 경둜둜 μ΄λ™ν•˜λ € ν•œλ‹€. μ΅œλ‹¨κ²½λ‘œλŠ” λ§΅μ—μ„œ κ°€μž₯ 적은 개수의 칸을 μ§€λ‚˜λŠ” 경둜λ₯Ό λ§ν•˜λŠ”λ°, μ΄λ•Œ μ‹œμž‘ν•˜λŠ” μΉΈκ³Ό λλ‚˜λŠ” 칸도 ν¬ν•¨ν•΄μ„œ μ„Όλ‹€.

λ§Œμ•½μ— μ΄λ™ν•˜λŠ” 도쀑에 ν•œ 개의 벽을 λΆ€μˆ˜κ³  μ΄λ™ν•˜λŠ” 것이 μ’€ 더 κ²½λ‘œκ°€ 짧아진닀면, 벽을 ν•œ 개 κΉŒμ§€ λΆ€μˆ˜κ³  μ΄λ™ν•˜μ—¬λ„ λœλ‹€.

ν•œ μΉΈμ—μ„œ 이동할 수 μžˆλŠ” 칸은 μƒν•˜μ’Œμš°λ‘œ μΈμ ‘ν•œ 칸이닀.

맡이 μ£Όμ–΄μ‘Œμ„ λ•Œ, μ΅œλ‹¨ 경둜λ₯Ό ꡬ해 λ‚΄λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

μž…λ ₯

첫째 쀄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진닀. λ‹€μŒ N개의 쀄에 M개의 숫자둜 맡이 주어진닀. (1, 1)κ³Ό (N, M)은 항상 0이라고 κ°€μ •ν•˜μž.

좜λ ₯

첫째 쀄에 μ΅œλ‹¨ 거리λ₯Ό 좜λ ₯ν•œλ‹€. λΆˆκ°€λŠ₯ν•  λ•ŒλŠ” -1을 좜λ ₯ν•œλ‹€.

 

풀이

일반 bfs λ¬Έμ œμ™€λŠ” 달리 벽을 λΆ€μˆ˜λŠ” κΈ°λŠ₯이 μΆ”κ°€λ˜μ—ˆλ‹€..

고민을 μ’€ 많이 ν–ˆλŠ”λ° κ·Έλƒ₯ 거리 ν‘œμ‹œν•˜λŠ” 이쀑배열을 λ‘κ°œλ‘œ λ§Œλ“€μ—ˆλ‹€ (결ꡭ은 삼쀑배열..)

벽을 ν•œλ²ˆμ΄λΌλ„ λΆ€μˆœ ν›„ μ§„ν–‰ν•˜λ©΄ dis[x][y][1] 에 기둝되고

벽을 ν•œλ²ˆλ„ λΆ€μˆ˜μ§€ μ•Šμ•˜λ‹€λ©΄ dis[x][y][0] 에 진행상황이 κΈ°λ‘λœλ‹€

 

삼쀑배열이라 pair κ°€ μ•„λ‹Œ tuple 을 μ‚¬μš©ν•΄μ•Όν–ˆκ³ 

bfs λ₯Ό 돌리며 μ΄λ™ν• λ•ŒλŠ” 벽을 λΆ€μˆ˜λŠ” κ²½μš°μ™€ μ•„λ‹Œκ²½μš°λ₯Ό λ‚˜λˆ μ„œ 이동할 수 있게 ν–ˆλ‹€

μ΄λ•Œ 쑰건을 μ‹ κ²½μ¨μ„œ 걸어쀬닀 (μ½”λ“œ μ°Έκ³ )

 

μ£Όμ˜ν•΄μ•Όν•  μš”μ†ŒλŠ”

1. 인풋에 띄어쓰기가 μ—†κΈ°λ•Œλ¬Έμ— board λ₯Ό char 둜 λ°›μ•„μ•Όν•œλ‹€

2. λ²½ λΆ€μˆ¨ μ—¬λΆ€λ₯Ό 기둝해놓고 좜λ ₯ν• λ•Œ 쑰건에 따라 좜λ ₯ν•΄μ•Όν•œλ‹€

3. μ§€λ‚˜κ°„ 칸의 갯수λ₯Ό 좜λ ₯ν•΄μ•Ό ν•˜κΈ°λ•Œλ¬Έμ— 초기 (0,0) 값을 1둜 λ‘¬μ•Όν•œλ‹€

이 정도?

// Authored by : seondal
// 풀이 : https://whkakrkr.tistory.com/
// Co-authored by : -

//#include <bits/stdc++.h>
#include <iostream>
#include <queue>

using namespace std;

int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};

int n,m;
char board[1002][1002];

int dis[1002][1002][2];
queue<tuple<int,int,int>> q;
bool broken = false;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    // μž…λ ₯
    cin >> n >> m;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin >> board[i][j];
            dis[i][j][0] = -1;
            dis[i][j][1] = -1;
        }
    }
    q.push({0,0,0});
    dis[0][0][0] = 1;
    dis[0][0][1] = 1;
    // 이 λ¬Έμ œλŠ” μ§€λ‚˜κ°„ 칸의 갯수λ₯Ό μΉ΄μš΄νŠΈν•΄μ•Όν•˜λ―€λ‘œ μ΄ˆκΉƒκ°’μ΄ 1인것에 주의
    
    // 계산
    while(!q.empty()){
        int cx,cy,cb;
        tie(cx,cy,cb) = q.front();
        q.pop();
        
        for(int dir=0; dir<4; dir++) {
            int x = cx + dx[dir];
            int y = cy + dy[dir];
            
            if(x<0 || x>=n || y<0 || y>=m) continue;
            
            // λΆ€μˆ˜μ§€ μ•ŠλŠ” 경우 -> 갈곳이 벽이 μ•„λ‹ˆκ³ , λ°©λ¬Έν•˜μ§€ μ•Šμ€κ²½μš°
            if(board[x][y]=='0' && dis[x][y][cb]==-1) {
                dis[x][y][cb] = dis[cx][cy][cb] + 1;
                q.push({x,y,cb});
            }
            
            // λΆ€μˆ˜λŠ” 경우 -> 아직 μ•ˆλΆ€μ…¨κ³ , 갈곳이 벽이고, λ°©λ¬Έν•˜μ§€ μ•Šμ€ 경우
            if(cb==0 && board[x][y]=='1' && dis[x][y][1]==-1) {
                dis[x][y][1] = dis[cx][cy][cb] + 1;
                q.push({x,y,1});
                broken = true;
            }
        }
    }
    
    if(broken)
        cout << dis[n-1][m-1][1];
    else
        cout << dis[n-1][m-1][0];
    
    return 0;
}

/*
 */
λ°˜μ‘ν˜•