Search
Duplicate

외판원 순회 (2098)

생성일
2021/03/20 18:19
태그

문제

풀이

완전 탐색으로 풀기
시작 도시 정하기
방문하지 않은 도시들 방문
마지막 도시에서 다시 시작도시로 방문
dp 적용
처음 도시에서 다시 처음도시로 돌아가는것이기 때문에 시작 도시가 중요하지 않다.
어자피 사이클이니까 어느 도시에서 시작하든 결과는 똑같다.
첫번째 도시에서 출발하는것으로 고정
현재 방문 상태 + 지금 도시 위치 기준으로 저장
1→2→5→3→4→1
1→5→2→3→4→1
여기서 3→4→1 이 겹침 dp[3][10111]로 해결
현재 방문 상태?
방문한 곳을 비트로 표현한다
N ≤ 16 이므로 dp 의 크기는 2^16 이다.
이때 지금 도시 위치에 따라 dp가 달라지기 떄문에
실제 dp의 크기는 16 * 2^16
현재 방문 상태만 보고 알수는 없나?
현재 도시에서 출발해야되기 떄문에 현재 방문 상태만으로는 절대 불가능하다
A→B 도시로 이동해놓고 C→D 로 가버릴수있기떄문
아직 dp를 이중배열로 생각하는게 서툴다.

구현

#include <iostream> #include <vector> #define INF 10000000 using namespace std; int n; int W[16][16]; int dp[16][65536]; void pre() { ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); } void input() { pre(); cin >> n; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> W[i][j]; } int rec(int curr, int visit) { int ret; visit |= (1 << curr); if (visit == ~(-1 << n)) return (W[curr][0] ? W[curr][0] : INF); if (dp[curr][visit]) return(dp[curr][visit]); ret = INF; for (int i = 1; i < n; i++) { if ((visit & (1 << i)) || W[curr][i] == 0) continue; ret = min(ret, rec(i, visit) + W[curr][i]); } dp[curr][visit] = ret; return (ret); } void solve() { cout << rec(0, 0) << endl; } int main(void) { input(); solve(); return (0); }
C++
복사