πŸ’» Computer Science/- Data Structure, Algorithm

[μ•Œκ³ λ¦¬μ¦˜ PS] λ°±μ€€ 10971번 μ™ΈνŒμ› 순회 2 μžλ°” λ¬Έμ œν’€μ΄

Wonit 2021. 2. 20. 15:21

문제

ν•΄λ‹Ή ν¬μŠ€νŒ…μ€ λ°±μ€€μ˜ 10971번 μ™ΈνŒμ› 순회 2 의 μ ‘κ·Όκ³Ό ν•΄κ²° 방법을 μ„€λͺ…ν•œ κΈ€ μž…λ‹ˆλ‹€.
μ •λ‹΅ μ†ŒμŠ€ μ½”λ“œλ₯Ό ν™•μΈν•˜μ‹œλ €λ©΄ solve url μ—μ„œ 확인 κ°€λŠ₯ν•©λ‹ˆλ‹€.

 

10971번: μ™ΈνŒμ› 순회 2

첫째 쀄에 λ„μ‹œμ˜ 수 N이 μ£Όμ–΄μ§„λ‹€. (2 ≤ N ≤ 10) λ‹€μŒ N개의 μ€„μ—λŠ” λΉ„μš© 행렬이 μ£Όμ–΄μ§„λ‹€. 각 ν–‰λ ¬μ˜ 성뢄은 1,000,000 μ΄ν•˜μ˜ μ–‘μ˜ μ •μˆ˜μ΄λ©°, 갈 수 μ—†λŠ” κ²½μš°λŠ” 0이 μ£Όμ–΄μ§„λ‹€. W[i][j]λŠ” λ„μ‹œ iμ—μ„œ j

www.acmicpc.net

이 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ–΄λ–€ λ°©μ‹μœΌλ‘œ μ ‘κ·Όν•΄μ•Ό ν•˜λŠ”μ§€λ₯Ό λ¨Όμ € μƒκ°ν•΄λ³΄μž.

문제 μ ‘κ·Ό

이번 λ¬Έμ œλŠ” CS λΆ„μ•Όμ—μ„œ 유λͺ…ν•œ 문제라고 ν•œλ‹€.


이 문제의 핡심은 λ‹€μŒκ³Ό κ°™λ‹€.

n by n ν–‰λ ¬μ—μ„œ (n, m)은 ν˜Ήμ€ arr[n][m]은 nμ—μ„œ m으둜 κ°€λŠ” λΉ„μš© 이닀.

μš°λ¦¬λŠ” 이 λΉ„μš©μ„ μ΅œμ†Œν™”ν•΄μ•Ό ν•œλ‹€.

 

μ•„λž˜μ™€ 같이 4 x 4 행렬이 μžˆλ‹€λ©΄

0 1 2 1
3 0 3 2
1 2 0 1
2 1 2 0

0 -> 1   1 -> 2   2 -> 3   3 -> 0 // μ΄λ ‡κ²Œ κ°€λ˜
1 -> 3   3 -> 2   2 -> 0   0 -> 1 // ν˜Ήμ€ μ΄λ ‡κ²Œ κ°€λ˜ 상관 μ—†μŒ

μ–΄λ–»κ²Œ κ°€λ˜ λͺ¨λ“  λ„μ‹œλ§Œ λ‹€ λ°©λ¬Έν•˜λ©΄ λœλ‹€.

 

그럼 λͺ¨λ“  λ„μ‹œλ₯Ό λ‹€ λ°©λ¬Έν•˜λ €λ©΄ μˆœμ—΄μ„ μ΄μš©ν•˜λ©΄ 될 것 κ°™λ‹€.

 

ν•˜μ§€λ§Œ μˆœμ—΄ μ•Œκ³ λ¦¬μ¦˜μ€ μ‹œκ°„ λ³΅μž‘λ„κ°€ N * N! κ°€ λœλ‹€.


N * N! λŠ” μ „ν˜€ μž‘μ§€ μ•Šμ€ μ‹œκ°„ λ³΅μž‘λ„μ΄λ‹ˆ μ΅œμ•…μ˜ κ²½μš°κΉŒμ§€ 계산해봐야 ν•˜λŠ”λ°, 10 * 10! = 36,288,000 으둜 2초 내에 ν•΄κ²°ν•  수 μžˆλŠ” μΆ©λΆ„ν•œ 양이 λœλ‹€.

 

그럼 μš°λ¦¬λŠ” λ„μ‹œλ₯Ό λ°©λ¬Έν•˜λŠ” μˆœμ„œλ₯Ό μˆœμ—΄λ‘œμ¨ λ‚˜νƒ€λ‚΄κ³  κ·Έ κ°€μ€‘μΉ˜λ“€λ§Œ 계산해주면 μˆœνšŒμ— ν•„μš”ν•œ μ΅œμ†Œ λΉ„μš©μ„ 찾을 μˆ˜μžˆμ„ 것 κ°™λ‹€.

해결법

λͺ¨λ“  μˆœμ—΄μ„ κ΅¬ν•˜κΈ° μœ„ν•΄μ„œ μš°λ¦¬λŠ” Next Permutation을 μ΄μš©ν•  것이닀.

private static boolean nextPermutation(int[] arr) {
    int i = arr.length-1;
    while(i > 0 && arr[i-1] >= arr[i]) i--;
    if(i <= 0) return false;

    int j = arr.length-1;

    while(arr[j] <= arr[i-1]) j--;

    swap(arr, i-1, j);
    j = arr.length - 1;
    while(i < j) {
        swap(arr, i, j);
        i++;
        j--;
    }
    return true;
}

private static void swap(int[] arr, int index1, int index2) {
    int temp = arr[index1];
    arr[index1] = arr[index2];
    arr[index2] = temp;
}

μ˜€λ‹΅ 후보

이 λ¬Έμ œμ—μ„œ κ°€μž₯ μ£Όμ˜ν•΄μ•Ό ν•˜λŠ” 것은 λ°”λ‘œ 이것이닀.

 

i λ„μ‹œμ—μ„œ j λ„μ‹œλ‘œ 갈 수 μ—†λŠ” κ²½μš°λ„ μ‘΄μž¬ν•œλ‹€. ν•˜μ§€λ§Œ μš°λ¦¬λŠ” λͺ¨λ“  λ„μ‹œλ₯Ό λŒμ•„μ•Ό ν•œλ‹€.

 

그럼 i λ„μ‹œμ—μ„œ j λ„μ‹œλ‘œ λͺ» κ°€λŠ” 경우, 예λ₯Ό λ“€λ©΄ 0 -> 1, 1 -> 2 λ§Œμ— λλ‚˜λŠ” κ²½μš°κ°€ 있으면 이 것은 정닡이 될 수 μ—†λ‹€.

 

μ™œ? λͺ¨λ“  λ„μ‹œλ₯Ό λ°©λ¬Έν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έ.

 

ν•˜μ§€λ§Œ 이 경우의 필터링을 ν•΄μ£Όμ§€ μ•ŠλŠ”λ‹€λ©΄ λͺ¨λ“  λ„μ‹œλ₯Ό λ°©λ¬Έν•˜μ§€ μ•Šμ•„λ„ μ΅œμ†Œ 값이 좜λ ₯될 수 μžˆλ‹€.

 

κ·ΈλŸ¬λ―€λ‘œ 이에 μœ μ˜ν•˜μž

μ •λ‹΅ μ½”λ“œ

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    static int[][] map;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        int n = input.nextInt();

        map = new int[n][n];
        int[] country = new int[n];
        for (int i = 0; i < n; i++) {
            country[i] = i;
            for (int j = 0; j < n; j++) {
                map[i][j] = input.nextInt();
            }
        }
        int answer = Integer.MAX_VALUE;
        do {
            int sum = 0;
            boolean flag = false;
            for (int i = 0; i < country.length - 1; i++) {
                if(map[country[i]][country[i+1]] == 0) flag = true;
                else sum += map[country[i]][country[i+1]];
            }
            int value = map[country[country.length - 1]][country[0]];
            if(!flag && value != 0) {
                sum += value;
                answer = Math.min(answer, sum);
            }
        }while(nextPermutation(country));
        System.out.println(answer);
    }

    private static boolean nextPermutation(int[] arr) {
        int i = arr.length - 1;
        while(i > 0 && arr[i-1] >= arr[i]) i--;
        if(i <= 0) return false;

        int j = arr.length - 1;
        while(arr[i-1] >= arr[j]) j--;
        swap(arr, i-1, j);

        j = arr.length - 1;
        while(i < j) {
            swap(arr, i, j);
            i++;
            j--;
        }
        return true;
    }

    private static void swap(int[] arr, int index1, int index2) {
        int temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }

}

μ •λ‹΅ μ†ŒμŠ€ μ½”λ“œλ₯Ό ν™•μΈν•˜μ‹œλ €λ©΄ solve url μ—μ„œ 확인 κ°€λŠ₯ν•©λ‹ˆλ‹€.