PS/Problems
[Java] 백준 2098번 외판원 순회 - TSP, 비트필드 DP
CalicoCat22
2022. 2. 20. 01:24
https://www.acmicpc.net/problem/2098
2098번: 외판원 순회
첫째 줄에 도시의 수 N이 주어진다. (2 ≤ N ≤ 16) 다음 N개의 줄에는 비용 행렬이 주어진다. 각 행렬의 성분은 1,000,000 이하의 양의 정수이며, 갈 수 없는 경우는 0이 주어진다. W[i][j]는 도시 i에서 j
www.acmicpc.net
- 현재까지 방문한 도시 번호에 대한 정보를 비트마스킹 (visit)
- wei는 a 도시에서 b도시로 갈 때의 거리
dp는 visit 상황에서 now 도시에 있을 때 목적지까지 가질 수 있는 최소 거리값
- 모든 도시를 방문하는 사이클이 단 1개 생기기 때문에 어느 도시를 시작점으로 잡아도 답은 같다.
==> 0번 도시를 시작점으로 잡아도 된다!
처음에는 N!의 시간복잡도를 가졌었지만
비트필드를 이용하여 시간복잡도를 N * 2^N 까지 줄인듯하다.
import java.util.*;
import java.io.*;
public class g1_2098 {
static FastScanner fs = new FastScanner();
static PrintWriter pw = new PrintWriter(System.out);
static int n, INF = 20000000;
static int[][] wei, dp;
public static void main(String[] args) {
n = fs.nextInt();
wei = new int[n][n];
dp = new int[(int)Math.pow(2, n)][n];
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
wei[i][j] = fs.nextInt();
if (wei[i][j] == 0) wei[i][j] = INF;
}
}
pw.print(solve(1, 0));
pw.close();
}
static int solve(int visit, int now){
if (visit == Math.pow(2, n) - 1){
dp[visit][now] = wei[now][0];
return dp[visit][now];
}
if (dp[visit][now] != 0) return dp[visit][now];
int temp = Integer.MAX_VALUE;
for (int i=0;i<n;i++){
if ((visit & (1 << i)) == 0){
temp = Math.min(temp, solve(visit | (1 << i), i) + wei[now][i]);
}
}
dp[visit][now] = temp;
return temp;
}
// ----------input function----------
static void sort(int[] a) {
ArrayList<Integer> L = new ArrayList<>();
for (int i : a)
L.add(i);
Collections.sort(L);
for (int i = 0; i < a.length; i++)
a[i] = L.get(i);
}
static class FastScanner {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer("");
String next() {
while (!st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
double nextDouble() {
return Double.parseDouble(next());
}
int[] readArray(int n) {
int[] a = new int[n];
for (int i = 0; i < n; i++)
a[i] = nextInt();
return a;
}
long nextLong() {
return Long.parseLong(next());
}
}
}