출처 : https://www.acmicpc.net/problem/2098
풀이 방법
외판원 문제를 비트마스킹과 DP를 활용해서 풀이하는 문제이다
DP를 2차원 배열로 선언한 후 dp[y][x] = y를 현재 지점 x를 현재 지점을 포함한 방문한 노드의 인덱스를 비트로 변경했을 때 값으로 설정한다.
ex 11001(2진수) -> 1, 4, 5번 방문
모든 지점을 방문했을 경우는 (1 << n) -1 이 된다 -> 011111 = 100000 - 1 (2진수)
아래와 같은 코드를 통해 i번 인덱스를 방문했는지 판단한다.
if((visited & (1 << i)) > 0) continue;
이후에는 일반적인 dp문제와 동일하게 풀이하면 된다.
import java.io.*;
import java.util.*;
public class Main {
static int n;
static int[][] W;
static int[][] dp;
static int ans;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
W = new int[n][n];
dp = new int[n][1 << n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
W[i][j] = Integer.parseInt(st.nextToken());
}
Arrays.fill(dp[i], -1);
}
System.out.println(dfs(0, 1));
}
static int dfs(int idx, int visited) { // 현재 idx이고 지금까지 방문한 것이 visited이다.
if (visited == (1 << n) - 1) { //모든 지점 방문했을 때
if (W[idx][0] == 0) return 987654321; // 돌아갈 수 없으면 큰 값 반환
return W[idx][0];
}
if(dp[idx][visited] != -1) {
return dp[idx][visited];
}
int ret = 987654321;
for (int i = 0 ;i < n;i++) {
if((visited & (1 << i)) > 0) continue;
if (W[idx][i] == 0) continue;
ret = Math.min(ret, dfs(i, visited | (1 << i)) + W[idx][i]);
}
dp[idx][visited] = ret;
return ret;
}
}'Algorithm' 카테고리의 다른 글
| [백준] 수영장 만들기 1113번 (java) (3) | 2025.06.17 |
|---|---|
| [백준] 우주 탐사선 17182번 (java) 플로이드 워샬, 순열 (1) | 2025.06.15 |
| [백준] 닭싸움 팀 정하기 1765번 Java (1) | 2025.06.13 |
| [프로그래머스] 홀짝트리 (java) 그래프 (1) | 2025.06.08 |
| [백준] 불켜기 11967번 (java) (0) | 2025.06.08 |