Algorithm/BOJ

[BOJ] μ™ΈνŒμ› 순회(2098)

vividswan 2022. 3. 11. 12:03

[λ°±μ€€(BOJ)] μ™ΈνŒμ› 순회(2098) C++

문제 : BOJ_2098번 μ™ΈνŒμ› 순회

문제 μ„€λͺ…

λΉ„νŠΈλ§ˆμŠ€ν‚Ή

n 개의 여행지가 μžˆμ„ λ•Œ, 각 μ—¬ν–‰μ§€μ—μ„œ λ‹€λ₯Έ μ—¬ν–‰μ§€λ‘œ 갈 수 μžˆλŠ” λΉ„μš©μ΄ μ£Όμ–΄μ§‘λ‹ˆλ‹€.

μ΄λ•Œ λΉ„μš©μ„ μ΅œμ†Œν•œμœΌλ‘œ ν•΄μ„œ μΆœλ°œν•œ μ—¬ν–‰μ§€μ—μ„œ λͺ¨λ“  여행지λ₯Ό λ°©λ¬Έν•œ λ’€ λ‹€μ‹œ μΆœλ°œν•œ μ—¬ν–‰μ§€λ‘œ λŒμ•„μ˜€λŠ” λΉ„μš©μ„ κ΅¬ν•˜λŠ” λ¬Έμ œμž…λ‹ˆλ‹€.

μ΄λ•Œ ν•œ 번 λ°©λ¬Έν–ˆλ˜ μ—¬ν–‰μ§€λŠ” λ‹€μ‹œ λ°©λ¬Έν•  수 μ—†μŠ΅λ‹ˆλ‹€.

λΉ„νŠΈ λ§ˆμŠ€ν‚Ή 외에도 μ—¬λŸ¬ 가지 λ°©λ²•μœΌλ‘œ ν•΄κ²°ν•  수 μžˆλŠ” 유λͺ…ν•œ λ¬Έμ œμž…λ‹ˆλ‹€.

μ—¬ν–‰μ§€μ˜ μˆ˜κ°€ μ΅œλŒ€ 16이기 λ•Œλ¬Έμ— 16개의 자리수λ₯Ό λ§Œλ“€κ³  λΉ„νŠΈ μ—°μ‚°μœΌλ‘œ λ°©λ¬Έν•œ 여행지λ₯Ό μ²΄ν¬ν•˜λŠ” λ°©μ‹μœΌλ‘œ λΉ„νŠΈ λ§ˆμŠ€ν‚ΉμœΌλ‘œ ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


Solution

recursion ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄ μ€λ‹ˆλ‹€.

μ΄λ•Œ, ν•¨μˆ˜μ˜ λ‚΄μš©μ€ recursion(ν˜„μž¬ λ„μ‹œ, λ°©λ¬Έν•œ λ„μ‹œλ“€)μž…λ‹ˆλ‹€.
μ΄λ•Œ ν•¨μˆ˜μ˜ 두 번째 인자인 λ°©λ¬Έν•œ λ„μ‹œλ“€μ— λŒ€ν•΄μ„  배열을 ν• λ‹Ήν•˜λŠ” 것이 μ•„λ‹Œ 16자리의 λΉ„νŠΈ μ—°μ‚°μžλ‘œ λ°©λ¬Έν•œ λ„μ‹œμ˜ 정보λ₯Ό 전달해 μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

ν˜„μž¬ λ„μ‹œμ—μ„œ for 문을 μˆœνšŒν•˜μ—¬ 갈 수 μžˆλŠ” μ—¬ν–‰μ§€λ‘œ λ‹€μ‹œ μž¬κ·€λ‘œ λ“€μ–΄κ°€κ³ , λΉ„νŠΈ λ§ˆμŠ€ν‚ΉμœΌλ‘œ λͺ¨λ“  λ„μ‹œμ— λ°©λ¬Έν–ˆμŒμ„ ν™•μΈν•œ λ’€, κ·Έ ν˜„μž¬ λ„μ‹œμ—μ„œ 처음 λ„μ‹œλ‘œ 이동할 수 μžˆλ‹€λ©΄ λͺ¨λ“  λΉ„μš©μ„ return ν•΄ μ€λ‹ˆλ‹€.

각각의 λ„μ‹œλ₯Ό λ°©λ¬Έν•  λ•Œμ˜ λΉ„μš©μ„ ν˜„μž¬ λΉ„μš©μ—μ„œ + ν•΄μ£Όλ©° μž¬κ·€λ₯Ό ν•˜κ³ , 이 μŒ“μΈ 값듀을 항상 min ν•¨μˆ˜λ‘œ μ΅œμ†Ÿκ°’μ„ κ΅¬ν•˜λ„λ‘ ν•˜μ—¬ μ΅œμ’… 값이 μ΅œμ†Œκ°€ λ‚˜μ˜€κ²Œ ν•΄μ•Ό ν•©λ‹ˆλ‹€.


Description

  • vis == (1 << N) - 1) 첫 번째 λ°©λ¬Έν•œ λ„μ‹œλ₯Ό 0번째둜 μ§€μ •ν–ˆκΈ° λ•Œλ¬Έμ— ν•΄λ‹Ή 쑰건이 λͺ¨λ“  λ„μ‹œλ₯Ό λ°©λ¬Έν•œ μ‘°κ±΄μž…λ‹ˆλ‹€.
  • vis & (1 << i) "&"λ₯Ό ν™œμš©ν•΄ ν˜„μž¬ 쑰건이 i 번 μ§Έ λ„μ‹œλ₯Ό λ°©λ¬Έν•œ μƒνƒœμΈμ§€ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
  • memset(dp, -1, sizeof(dp)) dp λ©”λͺ¨μ œμ΄μ…˜μ„ μœ„ν•΄μ„œ λͺ¨λ“  dp 값을 -1둜 μ΄ˆκΈ°ν™”ν•΄μ€λ‹ˆλ‹€.

#include <iostream>
#include <algorithm>
#include <cstring>
#define INF 9999999999
using namespace std;
int N;
int map[16][16];
int dp[16][1 << 16];
int recursion(int now, int vis) {
    int &ret = dp[now][vis];
    if (ret != -1) return ret;
    if (vis == (1 << N) - 1) {
        if (map[now][0] != 0) return map[now][0];
        else return INF;
    }
    ret = INF;
    for (int i = 0; i < N; i++) {
        if (vis & (1 << i) || map[now][i]==0) continue;
        ret = min(ret, recursion(i, vis | (1 << i)) + map[now][i]);
    }
    return ret;
}
int main(void) {
    cin >> N;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            cin >> map[i][j];
        }
    }
    memset(dp, -1, sizeof(dp));
    cout << recursion(0, 1) << '\n';
    return 0;
}