본문 바로가기
💻 컴퓨터 시스템

백준 2309, 일곱 난쟁이 (자바/java)

by 비타민찌 2022. 4. 11.
728x90

백준 2309, 일곱 난쟁이 (자바/java)

 

문제

왕비를 피해 일곱 난쟁이들과 함께 평화롭게 생활하고 있던 백설공주에게 위기가 찾아왔다. 일과를 마치고 돌아온 난쟁이가 일곱 명이 아닌 아홉 명이었던 것이다. 아홉 명의 난쟁이는 모두 자신이 "백설 공주와 일곱 난쟁이"의 주인공이라고 주장했다. 뛰어난 수학적 직관력을 가지고 있던 백설공주는, 다행스럽게도 일곱 난쟁이의 키의 합이 100이 됨을 기억해 냈다. 아홉 난쟁이의 키가 주어졌을 때, 백설공주를 도와 일곱 난쟁이를 찾는 프로그램을 작성하시오.

 

입력

아홉 개의 줄에 걸쳐 난쟁이들의 키가 주어진다. 주어지는 키는 100을 넘지 않는 자연수이며, 아홉 난쟁이의 키는 모두 다르며, 가능한 정답이 여러 가지인 경우에는 아무거나 출력한다.

 

출력

일곱 난쟁이의 키를 오름차순으로 출력한다. 일곱 난쟁이를 찾을 수 없는 경우는 없다.

[풀이]

9명중 2명의 스파이를 찾는 문제로,

경우의 수가 많지 않기 때문에 브루트포스 문제다.

 

* 경우의 수는 36이다.

스파이를 하나씩 찾아낸다고 가정해서 경우의 수를 구한 뒤

중복되는 경우의 수를 구해 나누면 된다.

우선 9명 중 첫번째 스파이를 판별하는 경우의 수는 9다.

남은 8명 중 두번째 스파이를 판별하는 경우의 수는 8이다.

여기서 중복되는 경우의 수를 생각해보면

1 2 3 4 5 6 7 8 9 중에서

1,2를 뽑거나 2,1을 뽑거나의 결과가 같기 때문에

위에서 구했던 두 경우의 수 9*8 = 72는 2번 중복된 경우의 수다.

그러므로 72/2=36. 경우의 수는 36이된다.

n*(n-1) / 2
 

 

1. 난쟁이 키 입력받기

        int[] arr = new int[9];
        int sum = 0;
        int spy1 = 0, spy2 = 0;
        
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(br.readLine());
            sum += arr[i];
        }

        Arrays.sort(arr);
 

우선 9명의 난쟁이를 저장할 배열을 만들고

난쟁이들의 키의 총 합을 저장할 변수 sum를 만든다.

가짜 난쟁이의 키를 저장할 변수 spy1, spy2도 만든다.

 

그리고 배열에 9 난쟁이의 키를 입력 받으면서,

[20, 7, 23, 19, 10, 15, 25, 8, 13]
 

키의 합을 sum에 저장하고

Arrays.sort로 키 배열을 오름차순 정렬한다.

[7,8,10,13,15,19,20,23,25]
 

 

* parallelSort로도 가능하지만 직접 해보니 sort가 효울적이었다.

큰 데이터 처리에는 ParallelSort, 작은 데이터 처리에는 sort가 좋다고 한다.

(배열의 크기가 크고, 배열의 요소들의 순서가 난수처럼 들쑥날쑥일때는 ParallelSort가 빠름)

 

2. 가짜 난쟁이 판별 (brute force)

for (int i = 0; i < arr.length - 1; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (sum - arr[i] - arr[j] == 100) {
                    spy1 = i;
                    spy2 = j;
                    break;
                }
            }
        }
 

이 문제의 핵심인 brute force 알고리즘 부분.

일곱 난쟁이 키의 합은 100이 되어야 한다.

따라서 sum - (i번쨰 난쟁이 키 - j번째 난쟁이 키) = 100 일때

난쟁이 i,j 가 스파이가 되는 것이다.

i와 j를 찾을때 까지 for 돌리다가 찾으면 각각 spy 변수에 넣어주고 break 해준다.

 

3. 진짜 난쟁이 출력

for (int i = 0; i < arr.length; i++) {
            if (i == spy1 || i == spy2)
                continue;
            System.out.println(arr[i]);
        }
        bw.flush();
        bw.close();
 

아까 구한 가짜 난쟁이의 키를 spy1, spy2에 저장해 뒀다.

for문으로 모든 난쟁이 키를 순서대로 돌며 배열에 저장하다가

spy1이나 spy2 값에 다다르면 (15, 25)

그 배열을 건너뛴다.

[7,8,10,13,19,20,23]
 
 

 

[전체코드]

import java.io.*;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int[] arr = new int[9];
        int sum = 0;
        int spy1 = 0, spy2 = 0;
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(br.readLine());
            sum += arr[i];
        }
        Arrays.sort(arr);
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (sum - arr[i] - arr[j] == 100) {
                    spy1 = i;
                    spy2 = j;
                    break;
                }
            }
        }
        for (int i = 0; i < arr.length; i++) {
            if (i == spy1 || i == spy2)
                continue;
            System.out.println(arr[i]);
        }
        bw.flush();
        bw.close();
    }
}

 

 


 

N의 상상력을 자극하는 문제였다 +_+

 

728x90

댓글