우주 탐사선 ana호는 어떤 행성계를 탐사하기 위해 발사된다. 모든 행성을 탐사하는데 걸리는 최소 시간을 계산하려 한다. 입력으로는 ana호가 탐색할 행성의 개수와 ana호가 발사되는 행성의 위치와 ana호가 행성 간 이동을 하는데 걸리는 시간이 2차원 행렬로 주어진다. 행성의 위치는 0부터 시작하여 0은 행렬에서 0번째 인덱스에 해당하는 행성을 의미한다. 2차원 행렬에서 i, j 번 요소는 i 번째 행성에서 j 번째 행성에 도달하는데 걸리는 시간을 나타낸다. i와 j가 같을 때는 항상 0이 주어진다. 모든 행성을 탐사하는데 걸리는 최소 시간을 계산하여라.
탐사 후 다시 시작 행성으로 돌아올 필요는 없으며 이미 방문한 행성도 중복해서 갈 수 있다.
첫 번째 줄에는 행성의 개수 N과 ana호가 발사되는 행성의 위치 K가 주어진다. (2 ≤ N ≤ 10, 0 ≤ K < N)
다음 N 줄에 걸쳐 각 행성 간 이동 시간 Tij 가 N 개 씩 띄어쓰기로 구분되어 주어진다. (0 ≤ Tij ≤ 1000)
모든 행성을 탐사하기 위한 최소 시간을 출력한다.
3 0
0 30 1
1 0 29
28 1 0
2
4 1
0 83 38 7
15 0 30 83
67 99 0 44
14 46 81 0
74
이 문제는 Floyd-Warshall(플로이드 와샬), DFS(깊이 우선 탐색) 알고리즘을 이용해서 풀 수 있었다. 한번 지나간 정거장을 다시 갈 수 있기 때문에 플로이드-와샬 알고리즘을 이용해서 전체 최단 거리를 구하고 DFS 알고리즘을 이용해서 각 정거장의 순서를 정해서 그 거리 중 최단거리를 구했다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
static int[][] map;
static int N;
static int ans = Integer.MAX_VALUE;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] input = br.readLine().split(" ");
N = Integer.parseInt(input[0]);
int start = Integer.parseInt(input[1]);
map = new int[N][N];
for(int i=0; i<N; i++) {
input = br.readLine().split(" ");
for(int j=0; j<N; j++)
map[i][j] = Integer.parseInt(input[j]);
}
for(int k=0; k<N; k++) {
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
map[i][j] = Math.min(map[i][j], map[i][k]+map[k][j]); //플로이드 와샬 알고리즘으로 최소 거리 구함
}
}
}
boolean[] visited = new boolean[N];
visited[start] = true;
dfs(visited, start, 0, 0);
System.out.println(ans);
}
public static void dfs(boolean[] visited, int temp, int sum, int depth) {
if(depth==N-1) {
ans = Math.min(ans, sum); //최단 거리 구하기
return ;
}
for(int i=0; i<N; i++) {
if(!visited[i]) {
visited[i] = true;
dfs(visited, i, sum+map[temp][i], depth+1); //안지나간 정거장 지나가기
visited[i] = false;
}
}
}
}