[SWEA 1247] 최적 경로
업데이트:
문제
- SWEA 1247번
- 문제의 저작권은 SW Expert Academy에 있습니다.
접근방식
회사좌표와 집좌표는 고정되므로 집좌표들의 순열을 구하고 나서 각 거리를 계산해 최소 거리를 구하면 되는 문제이다.
순열을 만들어야 하는 이유는 예를 들어 A→B→C와 B→C→A모두 순서에 따라 거리가 다르게 결정되기 때문이다.
나는 입력 받을 때 회사좌표와 집좌표 고객좌표 순서를 제대로 하지못해서 어이없게 3시간이동안 고민을 했다…
너무 어렵게 생각하지 않으면 쉽게 풀리는 문제!!
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.StringTokenizer;
//최적경로 - 순열
public class Swea_1247 {
static int N; // 고객의 수
static Point[] NList; // 고객 좌표 담을 배열
static boolean[] visited; // 순열 방문 체크 배열
static Point[] selected; // 순열 선택 배열
static int Answer; // 가장 짧은 경로
static Point company; // 회사 좌표
static Point home; // 집 좌표
static StringTokenizer st;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int totalCnt = Integer.parseInt(br.readLine());
for (int tc = 1; tc <= totalCnt; tc++) {
N = Integer.parseInt(br.readLine());
NList = new Point[N];
visited = new boolean[N];
selected = new Point[N];
st = new StringTokenizer(br.readLine());
// 회사 좌표
company = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
// 집 좌표
home = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
// 고객 좌표
for (int i = 0; i < N; i++) {
NList[i] = new Point(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
}
// 고객 순열을 만들어서 경우의 수 구하기
Answer = Integer.MAX_VALUE; // 최소 거리
permutation(0);
System.out.println("#" + tc + " " + Answer);
}
}
static List<Point> list;
// 순열 계산
static void permutation(int idx) { // idx: 선택한 고객 인덱스
int length = 0;
if (idx == N) {
//1. 회사 -> 고객 거리
length += getDist(company, selected[0]);
//2. 고객 끼리의 거리
for(int i=0; i<selected.length-1; i++)
length += getDist(selected[i], selected[i+1]);
//3. 고객 -> 집까지의 거리
length += getDist(selected[selected.length-1], home);
Answer = Answer > length ? length : Answer;
return;
}
for (int i = 0; i < N; i++) {
if (!visited[i]) { // 중복 방지
visited[i] = true;
selected[idx] = NList[i];
permutation(idx + 1);
visited[i] = false; // 다음 턴에서 또 뽑을 수 있도록
}
}
}
// 두 좌표 사이의 거리 계산
static public int getDist(Point p1, Point p2) {
return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
}
// 좌표정보 클래스
static class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}