본문 바로가기
Algorithm

[SWEA] 1247번: 최적 경로(Java)

by 옥돔이와 연근이 2022. 8. 30.
728x90
반응형

문제

삼성전자의 서비스 기사인 김대리는 회사에서 출발하여 냉장고 배달을 위해 N명의 고객을 방문하고 자신의 집에 돌아가려한다.

회사와 집의 위치, 그리고 각 고객의 위치는 이차원 정수 좌표 (x, y)로 주어지고 (0 ≤ x ≤ 100, 0 ≤ y ≤ 100)

두 위치 (x1, y1)와 (x2, y2) 사이의 거리는 |x1-x2| + |y1-y2|으로 계산된다.

여기서 |x|는 x의 절대값을 의미하며 |3| = |-3| = 3이다. 회사의 좌표, 집의 좌표, 고객들의 좌표는 모두 다르다.

회사에서 출발하여 N명의 고객을 모두 방문하고 집으로 돌아오는 경로 중 가장 짧은 것을 찾으려 한다.

회사와 집의 좌표가 주어지고, 2명에서 10명 사이의 고객 좌표가 주어질 때,

회사에서 출발해서 이들을

모두 방문하고

집에 돌아가는 경로 중 총 이동거리가 가장 짧은 경로를 찾는 프로그램을 작성하라.

여러분의 프로그램은 가장 짧은 경로의 이동거리만 밝히면 된다.

이 문제는 가장 짧은 경로를 ‘효율적으로’ 찾는 것이 목적이 아니다.

여러분은 모든 가능한 경로를 살펴서 해를 찾아도 좋다.

모든 경우를 체계적으로 따질 수 있으면 정답을 맞출 수 있다.

[제약사항]

고객의 수 N은 2≤N≤10 이다.

그리고 회사의 좌표, 집의 좌표를 포함한 모든 N+2개의 좌표는 서로 다른 위치에 있으며 좌표의 값은 0이상 100 이하의 정수로 이루어진다.

[입력]

가장 첫줄은 전체 테스트케이스의 수이다.

이후, 두 줄에 테스트 케이스 하나씩이 차례로 주어진다.

각 테스트 케이스의 첫째 줄에는 고객의 수 N이 주어진다. 둘째 줄에는 회사의 좌표,집의 좌표, N명의 고객의 좌표가 차례로 나열된다.

좌표는 (x,y)쌍으로 구성되는데 입력에서는 x와 y가 공백으로 구분되어 제공된다.

[출력]

총 10줄에 10개의 테스트 케이스 각각에 대한 답을 출력한다.

각 줄은 ‘#x’로 시작하고 공백을 하나 둔 다음 최단 경로의 이동거리를 기록한다. 여기서 x는 테스트 케이스의 번호다.

예제 입력 1

10
5
0 0 100 100 70 40 30 10 10 5 90 70 50 20
6
88 81 85 80 19 22 31 15 27 29 30 10 20 26 5 14
10
39 9 97 61 35 93 62 64 96 39 36 36 9 59 59 96 61 7 64 43 43 58 1 36
...

예제 출력 1

#1 200
#2 304
#3 366
...


🤦‍♀️ My Solution

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class SW_1247 {

    static int T, N, comY, comX, homeX, homeY, min;
    static int[][] cust; // 고객의 정보
    // 순열, 조합, 부분집합 -> 암기 수준으로 되어있어야함
    static int[] tgt;
    static boolean[] select;

    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        T = Integer.parseInt(br.readLine());

        for (int t = 1; t < T; t++) {
            min = Integer.MAX_VALUE;

            N = Integer.parseInt(br.readLine());// 고객수
            cust = new int[N][2];
            select = new boolean[N];
            tgt = new int[N]; //

            StringTokenizer st = new StringTokenizer(br.readLine());
            comY = Integer.parseInt(st.nextToken());
            comX = Integer.parseInt(st.nextToken());

            homeY = Integer.parseInt(st.nextToken());
            homeX = Integer.parseInt(st.nextToken());

            // N개 고객에 대한 정보
            for (int i = 0; i < N; i++) { // y:0 x:1
                cust[i][0] = Integer.parseInt(st.nextToken()); // y좌표
                cust[i][1] = Integer.parseInt(st.nextToken()); // x좌표

            }

            // 순열
            perm(0); // 0:tat의 맨 앞부터 채우겠다
            System.out.println("#" + t + " " + min);
        }
    }

    static void perm(int tgtIdx) {
        // 기저조건
        if (tgtIdx == N) {
            // compete code
            // 현재 순열의 경우의 수가 하나 완성된 상태
            // 거리계산 후 최솟값인지 확인, 갱신

            // 회사 -> 첫 번째 고객
            int sum = distance(comY, comX, cust[tgt[0]][0], cust[tgt[0]][1]);

            // 첫 번째 고객 -> 마지막 고객
            for (int i = 0; i < N - 1; i++) {
                sum += distance(cust[tgt[i]][0], cust[tgt[i]][1], cust[tgt[i + 1]][0], cust[tgt[i + 1]][1]);
            }

            // 마지막 고객 -> 집
            sum += distance(cust[tgt[N - 1]][0], cust[tgt[N - 1]][1], homeY, homeX);

            min = Math.min(min, sum);
            return;
        }

        // src(cust)의 N개의 고객 중 하나씩 선택해 가는 과정을 거친다
        // 단 이미 이전에 선택한 고객은 제외함
        for (int i = 0; i < N; i++) {
            if (select[i])
                continue; // 이미 선택된 고객이면 스킵
            select[i] = true;
            tgt[tgtIdx] = i;// 현재 tgrIdx자리에 i를 선택했으니 다음 자리를 보러간다
            perm(tgtIdx + 1);
            select[i] = false; // 다시 되돌려준다
        }
    }

    static int distance(int y1, int x1, int y2, int x2) {
        return Math.abs(y1 - y2) + Math.abs(x1 - x2);

    }

}

728x90

'Algorithm' 카테고리의 다른 글

[BJ] 1987번: 알파벳(Java)  (0) 2022.08.30
[BJ] 1206: DFS와 BFS(Java)  (0) 2022.08.30
[BJ] 3109: 빵집(Java)  (0) 2022.08.30
[정올] 1828: 냉장고(Java)  (0) 2022.08.30
[BJ] 1541번: 잃어버린 괄호(Java)  (0) 2022.08.30