Search
moon
sun

외판원 순회 (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++
복사