https://www.acmicpc.net/problem/10971
[난이도]
- Silver 2
[알고리즘]
- 백트래킹
[코드]
import java.io.*;
import java.util.*;
public class Main {
static int N, answer = Integer.MAX_VALUE;
static int[][] map;
static boolean[] visited;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
N = Integer.parseInt(br.readLine());
map = new int[N][N];
visited = new boolean[N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine(), " ");
for (int j = 0; j < N; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i = 0; i < N; i++) {
visited[i] = true;
backTracking(i, i, 0, 0);
}
System.out.println(answer);
}
/**
* @param start : 메서드 실행 전 위에서 정해줌
* @param now : 현재 내가 위치한 도시
* @param sum : 현재위치한 도시까지 사용한 비용
* @param depth
*/
static void backTracking(int start, int now, int sum, int depth) {
if (depth == N - 1) { // 모든 도시를 모두 방문한 경우, N-1인 이유는 백트래킹 메서드를 실행하기 전에 이미 방문함
if (map[now][start] != 0) { // 마지막 도시에서 처음 도시로 가는 비용 더하기
sum += map[now][start];
answer = Math.min(answer, sum); // 최종적으로 나온 비용
}
return;
}
for (int i = 0; i < N; i++) {
if (!visited[i]) { // 방문하지 않은 도시일경우
if (map[now][i] != 0) { // 갈수 있는 도시일경우
visited[i] = true; // 방문했다면 true
backTracking(start, i, sum + map[now][i], depth + 1);
visited[i] = false; // 방문이 끝나면 false
}
}
}
}
}
[풀이]
시작하는 도시가 1번도시로 고정이 아닌 어느도시에서 시작하든 최소비용을 찾는것이기 때문에 N번 반복한다.
for (int i = 0; i < N; i++) {
visited[i] = true;
backTracking(i, i, 0, 0);
}
백트래킹 메서드의 매개변수 start 는 순회를 시작한 도시의 위치로 메서드를 실행할 때 정해진다.
매개변수 now는 현재 내가 위치한 도시의 위치를 뜻한다.
매개변수 sum은 현재 내가 now에 올때까지 사용한 비용을 뜻한다.
매개변수 depth는 모든도시를 순회했는지 체크한다.
for문을 돌며 방문하지 않은 도시이며 map[i][j]가 0이 아닌도시(방문할 수 있는 도시) 라면 백트래킹을 재귀적으로 수행한다.
이때 넣어주어야 하는 매개변수들은 순회를 시작한 도시 start, 다음 방문할 도시 i, 현재까지 사용한 비용(sum) + 현재 위치에서 i까지 가는 비용(map[now][i]), depth + 1이다.
for (int i = 0; i < N; i++) {
if (!visited[i]) { // 방문하지 않은 도시일경우
if (map[now][i] != 0) { // 갈수 있는 도시일경우
visited[i] = true; // 방문했다면 true
backTracking(start, i, sum + map[now][i], depth + 1);
visited[i] = false; // 방문이 끝나면 false
}
}
}
depth 가 N-1이 되면 모든도시를 방문한 것이다. depth가 N이아닌 N-1인 이유는 순회를 시작한 도시는 메서드 실행전 체크하기 때문이다.
depth가 N-1이 되었다면 마지막 도착한 도시에서 순회를 시작한 도시로 돌아와야하기 때문에 map[now][start] != 0 이라면
sum += map[now][start]를 해주어 마지막 비용을 추가해준다.
if (depth == N - 1) { // 모든 도시를 모두 방문한 경우, N-1인 이유는 백트래킹 메서드를 실행하기 전에 이미 방문함
if (map[now][start] != 0) { // 마지막 도시에서 처음 도시로 가는 비용 더하기
sum += map[now][start];
answer = Math.min(answer, sum); // 최종적으로 나온 비용
}
return;
}
'코딩테스트' 카테고리의 다른 글
백준 14889: 스타트와 링크 [JAVA] (0) | 2024.05.09 |
---|---|
백준 2961: 도영이가 만든 맛있는 음식 [JAVA] (0) | 2024.05.09 |
백준 6603: 로또 [JAVA] (0) | 2024.05.08 |
백준 15657: N과 M (8) [JAVA] (0) | 2024.05.08 |
백준 15656: N과 M (7) [JAVA] (0) | 2024.05.08 |