출처 : jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=954&sca=3030
문제
태현이는 방학기간 동안 택배 알바를 해서 최고급 노트북을 장만하려고 한다.
오늘 배달해야 하는 장소를 한 번씩만 방문해서 물건을 모두 배달하고 다시 회사로 돌아와야 한다.
배달하는 장소에만 도착할 수 있다면 물건은 모두 배달할 수 있으므로 물건의 개수나 크기등은 고려하지 않아도 된다.
그런데 문제는 방문하는 순서를 어떻게 정할지가 고민이다.
어떤 장소에서 다른 장소로 이동하는 데에는 비용이 발생하는데 만약 방문하는 순서를 잘못 정하게 되면
알바비로 받은 돈을 모두 이동비용으로 사용하고 눈물을 흘릴지도 모른다.
태현이가 물건을 모두 배달하고 회사로 돌아오기 위한 최소의 비용을 계산하는 프로그램을 작성해 주자.
입력형식
첫 줄은 배달해야 하는 장소의 수 N(1≤N≤12)이 주어진다. 이때, 출발지(회사)는 1번이다.
둘째 줄은 N X N 크기의 장소와 장소를 이동하는 비용(0 ≤ 비용< 100)이 한 칸씩의 공백으로 구분하여 주어진다.
비용은 양방향이 아니라 단방향으로 가기 위한 비용이다.
예들 들어 첫 번째 행 두 번째 열에 적힌 비용은 1번 장소에서 2번 장소로 이동하기 위한 비용을 의미하며,
2번 장소에서 1번 장소로 이동하기 위한 비용은 두 번째 행 첫 번째 열에 주어진다.
장소 사이에 이동할 수 있는 방법이 없다면 비용을 0으로 표시한다.
출력형식
회사에서 출발하여 오늘 배달해야 하는 모든 장소를 한 번씩 들러 물건을 배달하고 회사에 돌아오기 위한 최소의 비용을 출력한다.
풀이
1. 순서에 따라 모든 곳을 들려야 하니까 순열 생각 = dfs ( 순열 공부하기 좋은 문제 )
+ 중간에 cost > answer ==> return ; // 백트랙킹 ( 가지치기 ) 필요
Why ? 맵의 크기가 최대 12개 => O(순열) = 12! -> 간당간당함.
2. 총 비용 구한 후, 가장 작은 애 구하면됨.
코드
import java.util.Scanner;
public class Main {
static int N;
static int answer = Integer.MAX_VALUE;
static boolean[] visited;
static int[][] map;
public static void dfs(int startX, int idx, int cost) {
// 기저조건
// 중간 비용이 정답보다 크다면 더이상 볼 필요가 없지.
if ( cost >= answer) {
return;
}
/// 다 골랐으면
if ( idx == N-1) {
// 다시 회사로 돌아오는 길이 있으면
if ( map[startX][0] !=0 ) {
answer = Math.min(answer, cost + map[startX][0]);
}
return;
}
for( int i=1; i<N; i++) { // 0은 회사니까
// 그쪽으로 가는 길이 있고 , 거기 방문한적 없으면
if ( map[startX][i] != 0 && !visited[i]) {
visited[i] = true; // 방문처리하고
dfs(i, idx+1, map[startX][i] + cost);
visited[i] = false;
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
map = new int[N][N];
visited = new boolean[N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
map[i][j] = sc.nextInt();
}
}
// 0번 장소에서 시작해서 모든 곳 돌고, 다시 0번으로 끝나야함.
// 1. visited 처리하기 어려우니까 0 부터 시작해서 일단 모든 곳 들리기
// 2. 모든 곳 들린다음에 마지막으로 다시 0번 가는길 있는 경우만 체크하기
dfs(0, 0, 0);
System.out.println(answer);
}
}
'알고리즘' 카테고리의 다른 글
[백준] 딱지놀이 14696 [JAVA] (0) | 2020.10.05 |
---|---|
[백준] 파이프옮기기1 17070 [JAVA] (0) | 2020.10.04 |
[백준] 소가 길을 건너간 이유 6 14466 [JAVA] (0) | 2020.10.03 |
[백준] 행렬 1080 [JAVA] (0) | 2020.10.02 |
[삼성 SW Expert Academy] 1767. 프로세서 연결하기 [JAVA] (0) | 2020.10.01 |