← 기록 / DP

TSP

일단 표제만 정리해두고, 나중에 심도있게 정리해볼 예정.

이 글의 목차
  1. TSP
  2. Bottom-up solution

TSP

일단 표제만 정리해두고, 나중에 심도있게 정리해볼 예정.

Bottom-up solution

int N;
ll w[16][16];
ll dp[1<<16][16];
// bit dp
// dp[4][110111]
// 0, 1, 3, 4, 5 번째 도시를 들렀고, 4번째 도시를 마지막에 들른 상태임

void solve() {
    scanf("%d", &N);
    FOR(i,0,N) {
        FOR(j,0,N) {
            scanf("%lld", &w[i][j]);
        }
    }

    memset(dp, 0x3F, sizeof(ll) * (1<<16) * 16);
    
    int allstate = 1 << N;
    for(int state = 1; state < allstate; ++state) {
        for(int cur = 0; cur < N; ++cur) {
            if ((1<<cur) & state) { // 이 때만 유효함
                if (__builtin_popcount(state) == 1) {
                    if (w[0][cur]) dp[state][cur] = w[0][cur]; // 0에서 출발한 것으로 고른다.
                    continue;
                }

                // 이전 기준으로 풀기
                int pstate = state ^ (1<<cur);
                for(int prev = 0; prev < N; ++prev) {
                    if (cur == prev) continue;
                    if (w[prev][cur] == 0) continue;
                    if ((1<<prev) & state) { // 이전에 있어야 함! cur은 없는거고
                        dp[state][cur] = min(dp[state][cur], dp[pstate][prev] + w[prev][cur]);
                    }
                }
                // next 기준으로 풀기
                // for(int next = 0; next < N; ++next) {
                //     if (cur == next) continue;
                //     if (!((1<<next) & state)) continue; // state에 있는 점만 취급함
                //     if (w[cur][next] == 0) continue; // 길 있어야 함

                //     dp[state][next] = min(dp[state][next], dp[state ^ (1<<next)][cur] + w[cur][next]);
                // }
            }
        }
    }

    // for(int i = 0; i < N; ++i) {
    //     printf("%lld\n", dp[(1<<N) - 1][i]);
    // }

    printf("%lld\n", dp[(1<<N) - 1][0]); // 0: 한바퀴 돌고 다시 0으로 오는 경우를 봐야 함
}