일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- Java
- 플러터 개발환경 설정
- 스프링
- 백준
- JAVA SPRING
- 자바
- 페이코 추천인코드
- php 프로그래밍
- 한정 분기
- php 프로그래밍 입문
- programmers
- 배열
- php 프로그래밍 입문 연습문제
- php 프로그래밍 입문 문제풀이
- php
- C
- 자바 스프링
- 파이썬
- php 프로그래밍 입문 솔루션
- 페이코 초대코드
- php 프로그래밍 입문 예제
- C언어
- SWEA
- php 프로그래밍 입문 3판
- Flutter
- 플러터
- spring
- 페이코 추천인
- 페이코 친구코드
- 최단 경로
Archives
- Today
- Total
04-09 05:30
ImJay
[Jungol/Java] 1681. 해밀턴 순환회로 본문
반응형
[Jungol/Java] 1681. 해밀턴 순환회로
JUNGOL
code_blocks 코드 보기
www.jungol.co.kr
문제 해석
해밀턴 순환회로 문제는 모든 도시를 한 번씩 방문하고 출발점으로 돌아오는 경로 중 가장 비용이 적게 드는 순회 경로를 찾는 문제이다. 이 문제는 그래프의 표현에서 완전 그래프 형태로 제시되며, 각 도시 간의 이동 비용이 그래프의 간선으로 주어진다. 도시 간 이동할 수 없는 경우 비용이 0으로 표시된다.
풀이 과정
이 문제의 풀이는 백트래킹 기법과 비트마스킹을 사용하여 효율적으로 접근한다. 각 도시를 방문할 때마다 방문했음을 표시하기 위해 비트마스크를 사용하고, 경로의 비용 합이 현재까지 구한 최소 비용보다 클 경우 더 이상 진행하지 않고 되돌아간다(가지치기). 모든 도시를 방문한 후 출발 도시로 돌아올 수 있는지 확인하고, 가능하다면 총 이동 비용을 최소값과 비교하여 갱신한다.
코드
import java.io.*;
import java.util.*;
public class Main {
int[][] graph; // 그래프 배열
int ans = Integer.MAX_VALUE; // 최소 비용을 저장할 변수
int[] sel; // 방문한 도시를 저장할 배열
public static void main(String[] args) throws IOException {
new Main().sol();
}
private void sol() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(br.readLine());
graph = new int[n][n];
StringTokenizer st;
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
graph[i][j] = Integer.parseInt(st.nextToken());
}
}
sel = new int[n];
dfs(1, 0, 0);
sb.append(ans);
bw.write(sb.toString());
bw.flush();
bw.close();
}
private void dfs(int k, int visited, int sum) {
if (sum > ans) return; // 현재 경로 비용이 최소 비용보다 크면 중단
if (k == graph.length) {
if (graph[sel[k-1]][0] == 0) return; // 출발 도시로 돌아갈 수 없으면 중단
sum += graph[sel[k-1]][0]; // 출발 도시로 돌아가는 비용 추가
ans = Math.min(ans, sum); // 최소 비용 갱신
return;
}
for (int i = 1; i < graph.length; i++) {
if ((visited & (1 << i)) == 0 && graph[sel[k-1]][i] != 0) { // 방문하지 않았고, 이동 가능하면
sel[k] = i;
sum += graph[sel[k-1]][i]; // 비용 추가
dfs(k + 1, visited | (1 << i), sum); // 다음 도시 방문
sum -= graph[sel[k-1]][i]; // 방문 취소
}
}
}
}
시간 복잡도 분석
이 알고리즘의 시간 복잡도는 최악의 경우 O(n!)이다. 각 도시를 방문할 때마다 남은 도시들을 방문하는 모든 경우의 수를 고려하기 때문에, 도시의 수가 증가함에 따라 계산량이 팩토리얼로 증가한다.
느낀점
해밀턴 순환회로 문제는 NP-완전 문제로 알려져 있어, 효율적인 해결이 중요하다. 비트마스킹과 가지치기를 활용한 백트래킹 방식은 이러한 유형의 문제에서 계산량을 상당히 줄일 수 있어 매우 유용하다. 이번 풀이를 통해 보다 효과적인 문제 해결 방법과 최적화 기법에 대해 더 깊이 이해할 수 있었다.
반응형
'JUNGOL' 카테고리의 다른 글
[JUNGOL/Java] 2097. 지하철 (0) | 2024.04.18 |
---|---|
[JUNGOL/Java] 1828. 냉장고 (0) | 2024.04.18 |
Comments