🔹 문제 개요:
어떤 도시들이 있고, 도시 간 이동 비용(거리)이 주어진다고 하자.
📌 예제 입력 (도시 4개, 거리 행렬)
0 1 2 3
0 [0, 10, 15, 20]
1 [10, 0, 35, 25]
2 [15, 35, 0, 30]
3 [20, 25, 30, 0]
각 값 dist[i][j]는 도시 i에서 j로 가는 비용을 의미한다.
예를 들어:
✔ 모든 도시를 정확히 한 번씩 방문한 후, 다시 출발 도시로 돌아오는 최소 비용 경로를 찾는 것
✔ 즉, 가장 짧은 "순회 경로"를 찾는 것!
비용: 0 → 1 (10) + 1 → 2 (35) + 2 → 3 (30) + 3 → 0 (20) = 95
비용: 0 → 2 (15) + 2 → 1 (35) + 1 → 3 (25) + 3 → 0 (20) = 95
비용: 0 → 1 (10) + 1 → 3 (25) + 3 → 2 (30) + 2 → 0 (15) = 80 ✅ 최소 비용!
📌 즉, 최소 비용 경로는 0 → 1 → 3 → 2 → 0이며, 비용은 80! 🚀
✔ "모든 도시를 방문해야 한다" → 단순한 최단 경로 문제와 다름
✔ "한 번 방문한 도시는 다시 방문하면 안 된다"
✔ "모든 경로를 탐색해야 할 수도 있음 (완전 탐색 필요)"
✔ "비트마스크 + DP를 사용하면 최적화 가능"
N // 도시 개수 (1 ≤ N ≤ 16)
dist // N x N 크기의 거리 행렬
📌 예제 입력
4
0 10 15 20
10 0 35 25
15 35 0 30
20 25 30 0
최소 이동 비용을 출력
📌 예제 출력
80
✔ 완전 탐색 (Brute Force, 순열)
✔ DP + 비트마스크 (O(N^2 * 2^N))
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define INF 987654321
#define MAX_N 16
int n, dist[MAX_N][MAX_N];
int dp[MAX_N][1 << MAX_N]; // dp[i][visited]: i번 도시에서 visited 상태일 때 최소 비용
// 외판원 문제 해결 (DP + 비트마스크)
int tsp(int here, int visited) {
if (visited == (1 << n) - 1) { // 모든 도시 방문 완료
return dist[here][0] ? dist[here][0] : INF; // 시작 도시로 복귀
}
int& ret = dp[here][visited]; // DP 값 참조
if (ret != -1) return ret; // 이미 계산된 경우 반환
ret = INF;
for (int i = 0; i < n; i++) {
if (visited & (1 << i)) continue; // 이미 방문한 도시면 건너뜀
if (dist[here][i] == 0) continue; // 이동할 수 없는 도시 건너뜀
ret = min(ret, tsp(i, visited | (1 << i)) + dist[here][i]); // 최소 비용 갱신
}
return ret;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> dist[i][j];
}
}
fill(&dp[0][0], &dp[MAX_N - 1][(1 << MAX_N)], -1); // DP 배열 초기화
cout << tsp(0, 1) << '\n'; // 0번 도시에서 시작하여 최소 비용 계산
return 0;
}
📌 입력:
4
0 10 15 20
10 0 35 25
15 35 0 30
20 25 30 0
📌 연산 흐름:
1️⃣ tsp(0, 0001) → 0번 도시 방문 후 탐색
2️⃣ tsp(1, 0011) → 1번 도시 방문 후 탐색
3️⃣ tsp(3, 1011) → 3번 도시 방문 후 탐색
4️⃣ tsp(2, 1111) → 2번 도시 방문 후 시작 도시(0)로 복귀
5️⃣ 최소 비용 80 반환
📌 출력:
80
✔ 외판원 문제(TSP)는 "모든 도시를 한 번씩 방문하고 출발 도시로 돌아오는 최소 비용 경로"를 찾는 문제
✔ 완전 탐색(O(N!))은 비효율적이므로 DP + 비트마스크(O(N^2 * 2^N))를 사용하면 최적화 가능
✔ 비트마스크(int visited)를 활용하면 방문 상태를 정수 하나로 표현하여 효율적인 DP 테이블 관리 가능
✔ 최종 결과: 입력 예제의 경우 최소 비용은 80! 🚀🔥
소수 구하기//백준 (0) | 2025.03.31 |
---|---|
DFS 긍정왕 홍철이의 구걸 여행 (0) | 2025.03.03 |
BJ 2225 합분해 (0) | 2025.02.20 |
BJ9251 LCS(Longest Common Subsequence, 최장 공통 부분 수열) (0) | 2025.02.19 |
백준 11053 가장 긴 증가하는 부분 수열 LIS+DP (0) | 2025.02.18 |