순회판매원 문제 알고리즘은 헤밀턴 순회의 응용문제입니다.
* 헤밀턴 순회란?
출발점으로부터 모든 정점을 한번씩만 지나서 출발점으로 돌아오는 순회를 의미합니다.
순회판매원 문제는 판매원이 각 도시를 한 번만 방문하여 출발점으로 되돌아오는 최소 경로를 구해야합니다.
이 최소의 경로가 "최적"의 경로라고 할 수 있는데 일반적인 해결 알고리즘이 존재하지 않습니다.
이 때, "최근접 이웃 방법"을 통하여 최소값은 아니더라도 근사값을 구할 수 있습니다.
본 코드는 최근접 이웃 방법 알고리즘을 이용하여 모든 정점에서 최소값의 근사값을 구한 후 그 중 최소값을 출력합니다.
위의 그림의 최소경로는 2->3->1->4->2이며 그값은 75입니다.
필요한 변수
- 정점의 개수를 나타내는 n
- 정점사이의 경로값을 나타내는 이차원 배열 c
- 모든 정점들의 집합인 all, v <List>
- 최소경로를 나타내는 minW <int>
- 최소경로를 가지는 정점을 담는 집합 p <List>
핵심
모든 정점의 경우를 다 고려한 코드이며, all의 각각의 정점을 통해 접근합니다.
이 때, 사용되는 v는 all의 각 원소의 최소경로를 구하기 위해 사용되는 임시 집합입니다.
각 경로의 최소값을 가지는 정점을 p집합에 더해가면서 v에서는 그 정점을 지웁니다.
v집합이 공집합이 될 경우 작업을 종료하고 최종경로를 구합니다.
그 값을 최소경로의 값인 minW와 비교하여 minW보다 작으면 minW의 값을 변경합니다.
출력
최소경로를 출력합니다.
코드
public static void main(String[] args){
int n = 4;
int[][] c = {
, , ,
,
};
ArrayList<Integer> all = new ArrayList<Integer>();
for(int i=1; i<=n; i++)
int minW = Integer.MAX_VALUE;
for(int j=0; j<all.size(); j++){
ArrayList<Integer> v = new ArrayList<Integer>();
v.addAll(all);
int w = 0;
Integer v1 = all.get(j);
Integer _v = v1;
v.remove(_v);
ArrayList<Integer> p = new ArrayList<Integer>();
p.add(v1);
while(v.size()>0){
Integer mIdx = 0;
Integer min = 100000;
for(Integer i : v){
if(c[_v][i]==0)
if(min > c[_v][i]){
mIdx = i;
min = c[_v][i];
}
}
p.add(mIdx);
v.remove(mIdx);
w += min;
_v = mIdx;
}
w += c[_v][v1];
System.out.println("경로 : "+p);
System.out.println("최소경로 : "+w);
if(minW > w)
}
System.out.println("최소 경로 : " + minW);
}
결과
참고 문헌: DISCRETE MATHEMATICS 이산수학 Express - 7장 그래프 응용, 순회판매원 문제 알고리즘
'[개발] 알고리즘' 카테고리의 다른 글
백준 1152 - 단어의 개수 자바로 풀기 (0) | 2017.11.19 |
---|---|
백준 2448 - 별찍기 11(Fractal: 프랙탈) 자바로 풀기 (0) | 2017.11.17 |
너비 우선 탐색(Breath First Search : BFS) 알고리즘 자바로 구현하기 (0) | 2017.11.10 |
깊이 우선 탐색(Depth First Search : DFS) 알고리즘 자바로 구현하기 (0) | 2017.11.10 |
다익스트라(Dijkstra) 알고리즘 자바로 구현하기 (0) | 2017.11.07 |