IT 기획의 길

백준 17087번 숨바꼭질6 [JAVA] 본문

알고리즘(백준)/수학

백준 17087번 숨바꼭질6 [JAVA]

완벽하기 쉽지 않지만 완벽해지려고 노력해야 한다 2021. 1. 9. 16:02

문제

수빈이는 동생 N명과 숨바꼭질을 하고 있다. 수빈이는 현재 점 S에 있고, 동생은 A1, A2, ..., AN에 있다.

수빈이는 걸어서 이동을 할 수 있다. 수빈이의 위치가 X일때 걷는다면 1초 후에 X+D나 X-D로 이동할 수 있다. 수빈이의 위치가 동생이 있는 위치와 같으면, 동생을 찾았다고 한다.

모든 동생을 찾기위해 D의 값을 정하려고 한다. 가능한 D의 최댓값을 구해보자.

입력

첫째 줄에 N(1 ≤ N ≤ 105)과 S(1 ≤ S ≤ 109)가 주어진다. 둘째 줄에 동생의 위치 Ai(1 ≤ Ai ≤ 109)가 주어진다. 동생의 위치는 모두 다르며, 수빈이의 위치와 같지 않다.

출력

가능한 D값의 최댓값을 출력한다.

 

 

 

알고리즘 설계

 

수빈이의 위치 S에서 동생들이 있는 위치 A1,A2 -- An 까지  S+D 혹은 S-D로 모두 도착하려면  

D값은 [S-A1]과 [S-A2] --- [S-A3]의 약수여야한다

그중에서 D의 최댓값을 구하라고 했으므로  [S-A1]과 [S-A2] --- [S-A3]의 최대공약수를 구하면 되는 문제이다 

 

여기서 POINT는 N개의 수의 최대공약수를 어떻게 구해야지 효율적이냐는 것이다

 

처음에 나는 이중 for문을 사용하여 모든 수를 서로 짝을 이루어 GCD메소드로 넘겨 두 수의 최대공약수를 구하고 그 중에서 가장 작은값이 모든 수의 최대공약수라고 생각하고 구현을 하였다 

이는 답은 맞지만 시간초과를 발생시켰다

 

그 이후에 백준 강의를 보니 이보다 더 효율적으로 N개의 수의 최대공약수를 구하는 방법이 있었다

 

4개의 수 a,b,c,d가 있다면 

1. a,b의 최대공약수를 구하고

2, 1에서 얻은 값과 c의 최대공약수를 구하고

3. 2에서 얻은 값과 d의 최대공약수를 구하면 

4. 3에서 나온 값이 4개의 수의 최대공약수였다

 

 

느낀점: 알고리즘문제를 보고 어떻게 풀까 계속 고민하는것도 좋지만 효율적인 알고리즘 방법을 빨리빨리 습득해서 점점 문제에 효율적으로 접근하는 실력을 기르는것도 중요하다는것을 깨닫았다. 

 

 

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int s = sc.nextInt();
        int[] brother = new int[n];
        for (int i = 0; i < n; i++) {
            brother[i] = sc.nextInt();
            brother[i] = Math.abs(s - brother[i]);

        }

        int answer=brother[0];
        for (int i = 1; i < brother.length; i++) {
            answer=GCD(answer,brother[i]);

        }
        System.out.print(answer);
    }
    public static int GCD ( int a, int b){
        if (b == 0) {
            return a;
        } else {
            return GCD(b, a % b);
        }
    }
}