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

λ‚œμ΄λ„ : κ³¨λ“œ 4

κ±Έλ¦° μ‹œκ°„ : 였래 κ±Έλ¦Ό

문제

λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ° 문제 λ³΄λŸ¬κ°€κΈ°

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

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

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

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

 

풀이

  • λͺ¨λ“  경둜λ₯Ό μ‚΄νŽ΄λ³Ό ν•„μš”μ—†μ΄ μ΅œλ‹¨ 경둜λ₯Ό κ΅¬ν•˜λ©΄ λ˜λ―€λ‘œ bfsλ₯Ό μ΄μš©ν•œλ‹€.
  • 벽을 λΆ€μˆ˜κ³  이동할 수 μžˆμœΌλ―€λ‘œ 벽을 λΆ€μ‰ˆλŠ”μ§€μ˜ μ—¬λΆ€κΉŒμ§€ λ©”λͺ¨μ΄μ œμ΄μ…˜ ν•΄μ•Όν•œλ‹€.

 

μ½”λ“œ

[dfs] => ν‹€λ¦° μ½”λ“œ

#include <iostream>
#include <string>
#include <cstring>

using namespace std;

int N, M;
int map[1001][1001];
int direction[4][2] = { {0,1},{-1,0},{0,-1},{1,0} };
int memo[1001][1001][2];

int shortestPath(bool brakeRemain, int r, int c) {
    if (r == N - 1 && c == M - 1)
        return 1;
    int minPath = 1e8;
    for (int i = 0; i < 4; i++) {
        int rp = r + direction[i][0];
        int cp = c + direction[i][1];
        int type = 0;

        if (rp < 0 || cp < 0 || rp >= N || cp >= M) // 맡 μ•ˆμ— μ—†μœΌλ©΄
            continue;
        if (brakeRemain)
            type = 1;

        int res;
        if (map[rp][cp] == 0) {
            if (memo[rp][cp][type] != -1)
                res = memo[rp][cp][type];
            else {
                memo[rp][cp][type] = 1e8;
                res = shortestPath(brakeRemain, rp, cp) + 1;
                memo[rp][cp][type] = res;
            }
            if (minPath > res)
                minPath = res;
        }
        else {
            // 벽이면
            if (!brakeRemain) // λΆ€μˆ  수 μ—†μœΌλ©΄ κ±΄λ„ˆλ›°κΈ°
                continue;
            if (memo[rp][cp][0] != -1) // λ©”λͺ¨μ΄μ œμ΄μ…˜
                res = memo[rp][cp][0];
            else {
                memo[rp][cp][0] = 1e8; // λ‹€μ‹œ λ˜λŒμ•„μ˜€μ§€ λͺ»ν•˜κ²Œ
                res = shortestPath(!brakeRemain, rp, cp) + 1;
                memo[rp][cp][0] = res;
            }
            if (minPath > res)
                minPath = res;
        }
    }

    return minPath;
}

int main() {
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        string str;
        cin >> str;
        for (int j = 0; j < str.size(); j++) {
            map[i][j] = str[j]-'0';
        }
    }
    memset(memo, -1, sizeof(memo));

    int res = shortestPath(true, 0, 0);
    if (res >= 1e8)
        res = -1;
    cout << res;

}

[bfs] => 성곡 μ½”λ“œ

#include <iostream>
#include <string>
#include <cstring>
#include <queue>

using namespace std;

int N, M;
int map[1001][1001];
int direction[4][2] = { {0,1},{-1,0},{0,-1},{1,0} };
int memo[1001][1001][2];

struct Node {
    int r;
    int c;
    bool breakRemain = true;
    int p;
    Node(int row, int col, bool b) {
        r = row; c = col; breakRemain = b; p = 0;
    }
    Node(int row, int col, bool b, int path) {
        r = row; c = col; breakRemain= b; p = path;
    }
};

int main() {
    // 11μ‹œ 40λΆ„ μ‹œμž‘
    // λ²½ ν•˜λ‚˜λŠ” λΆ€μˆ΄λ„ 됨
    // μƒν•˜μ’Œμš° 이동
    // μ΅œλ‹¨ 경둜
    // n,m 은 1000μ΄ν•˜
    // λΆˆκ°€λŠ₯ μ‹œ -1
    // μž‘μ€ 문제 : ν•΄λ‹Ή μΉΈμ—μ„œ λ§ˆμ§€λ§‰κΉŒμ§€μ˜ μ΅œλ‹¨ 경둜
    // μž…λ ₯ : μ§€κΈˆκΉŒμ§€ 벽을 λΆ€μˆœμ μ΄ μžˆλŠ”μ§€, ν˜„μž¬ μΉΈ
    // 좜λ ₯ : μ΅œλ‹¨ 경둜
    // λ©”λͺ¨μ΄μ œμ΄μ…˜ : ν•΄λ‹Ή μΉΈ, λ²½ λΆ€μˆ¨ μ—¬λΆ€
    // μ’…λ£Œ : λ§ˆμ§€λ§‰ 칸에 도달, 더 갈곳이 μ—†κ³  λ²½λΆ€μˆ¨λ„ μ—†μŒ

    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        string str;
        cin >> str;
        for (int j = 0; j < str.size(); j++) {
            map[i][j] = str[j]-'0';
        }
    }
    memset(memo, -1, sizeof(memo));

    queue<Node*> que;
    que.push(new Node(0, 0, true));
    memo[0][0][0] = 0;
    memo[0][0][1] = 0;

    int flag = 1;
    while (!que.empty()) {
        Node* node = que.front(); que.pop();
        int r = node->r; int c = node->c; bool b = node->breakRemain;
        int path = node->p +1;
        if (r == N - 1 && c == M - 1) {
            // λ§ˆμ§€λ§‰ 도착
            flag = 0;
            cout << path;
            break;
        }
        for (int i = 0; i < 4; i++) {
            int rp = r + direction[i][0];
            int cp = c + direction[i][1];
            if (rp < 0 || cp < 0 || rp >= N || cp >= M) // 맡 μ•ˆμ— μ—†μœΌλ©΄
                continue;
            if (memo[rp][cp][b ? 1 : 0] != -1) // 이미 ν–ˆλ˜ 곳이면
                continue;

            if (map[rp][cp] == 0) {
                // 벽이 μ•„λ‹ˆλ©΄
                que.push(new Node(rp, cp, b, path));
                memo[rp][cp][b ? 1 : 0] = path;
            }
            else {
                // 벽이면
                if (!b) // λ²½λΆ€μˆ˜κΈ°κ°€ μ—†μœΌλ©΄
                    continue;
                que.push(new Node(rp, cp, false, path));
                memo[rp][cp][b ? 1 : 0] = path;
            }
        }
    }
    if (flag) {
        cout << -1;
    }
}

 

κ²°κ³Ό

λ°˜μ‘ν˜•