SIU
article thumbnail

 

 

문제 링크

 

2309번: 일곱 난쟁이

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

www.acmicpc.net

 

접근법

[백준 일곱 난쟁이 2309] 는 브루트 포스 기법을 이용해서 푸는 스페셜저지 문제이다. 스페셜저지 문제는 문제의 정답이 여러 가지일 때 유저가 출력한 답이 맞는지 안 맞는지 확인하는 문제이다. 이 문제에서는 9명의 키가 주어진다. 그리고 9명의 키 중에 7개를 골라서 합이 100이 되는 7명을 찾고 그 7명의 키를 오름차순으로 출력해주면 된다.

답이 여러개가 존재할 수도 있어 한 번 일곱 난쟁이가 정해지고 출력을 해주면 flag 변수로 답이 한 번만 출력되고 더이상 탐색(출력)되지 않도록 해야한다.

 

9명중 7명을 뽑는 조합 ! (무작위로 뽑기 때문에 순서가 상관 없음) 을 사용해야한다. 이 문제는 조합의 기본 문제로 9C2 = 9C7과 같다. 9명의 난쟁이 중에서 7명의 난쟁이를 선택하는 것은 다른 말로 9명의 난쟁이 중 포함되지 않는 2명의 난쟁이를 찾으면 된다. (순서 상관 없음)


9명중 2명을 뽑는 조합 ! (무작위로 뽑기 때문에 순서가 상관 없음)  => 이중 for문으로 브루트 포스 알고리즘 (완전 탐색)
9명 중 7명을 선택 == 9명 중 2명을 제외 따라서 제외할 2명의 조합을 모두 탐색하면서 조건에 맞는 지 확인한다.

 

성능 요약

메모리: 14160 KB, 시간: 120 ms

 

분류 : 브루트포스 알고리즘(bruteforcing), 정렬(sorting)

 

전체 코드 (JAVA)

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

public class BOJ_B1_2309_일곱난쟁이 {
	static int sum =0;
	static int[] arr;
	static boolean flag;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		arr = new int[9];
		for (int i = 0; i < 9; i++) {
			arr[i] = Integer.parseInt(br.readLine());
			sum += arr[i]; // 난쟁이 9명의 키의 합
		}
		// 순차 정렬
		Arrays.sort(arr);
		for (int i = 0; i < arr.length; i++) { //브루트 포스
			for (int j = 0; j < arr.length; j++) {
				// dfs는 flag로 백트레킹, 난쟁이 키는 다 달라서 인덱스가 겹칠 수 없음
				if(!flag &&i!=j) comb(i, j);
			}
		}
	}
	private static void comb(int idx1, int idx2) {
		int count = arr[idx1] + arr[idx2];
		StringBuilder st = new StringBuilder();
		if(sum-count==100) {
			for(int person : arr) {
				if(person!=arr[idx1] && person!=arr[idx2]) st.append(person).append("\n");
			}
			System.out.print(st);
			flag = true;
		}
	}
}

 

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

public class Main {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		int[] high = new int[9];
		int sum = 0;
		int spyA = 0, spyB = 0;

		for (int i = 0; i < high.length; i++) { // 난쟁이 키 입력
			high[i] = sc.nextInt();
			sum += high[i]; // sum은 난쟁이 9명의 키의 합
		}
		Arrays.sort(high); //키를 오름순서로 정렬
		
		for(int a = 0; a < high.length-1; a++) { //브루트 포스
			for(int b = a+1; b < high.length; b++) {
				if(sum - high[a] - high[b] == 100) { //핵심
					spyA = a;
					spyB = b;
					break;
				}
			}
		}
		
		for(int j = 0; j < high.length; j++) { // 진짜 난쟁이 키 출력
			if(j == spyA || j == spyB) //주의
				continue;
			System.out.println(high[j]);
		}
		sc.close();
	}
}

 

조합 코드 (1)

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

public class Main {

    static int[] dwarf = new int[9]; // 입력받을 아홉 난쟁이
    static int[] seven = new int[7]; // 임시로 저장할 일곱 난쟁이
    static int[] answer = new int[7]; // 답이 될 일곱 난쟁이

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

        for (int i = 0; i < 9; i++) {
            dwarf[i] = sc.nextInt();
        }
        Arrays.sort(dwarf); // 입력받은 아홉 난쟁이 정렬
        combination(0, 0, 0); // 조합

        for (int a : answer) { // 답 출력
            System.out.println(a);
        }

    }

    private static void combination(int cnt, int start, int sum) {
        if (cnt == 7) {
            if (sum == 100) { // 합이 100일 때 답에 해당 일곱 난쟁이를 저장
                for (int i = 0; i < 7; i++) {
                    answer[i] = seven[i];
                }
            }
            return;
        }

        for (int i = start; i < 9; i++) {
            seven[cnt] = dwarf[i];
            combination(cnt + 1, i + 1, sum + dwarf[i]);
        }
    }
}


조합 코드 (2)

import java.io.InputStreamReader;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.IOException;
 
public class BOJ2309 {
 
    static int N = 9, K = 100;
    static int child[] = new int[N];
    static int realChild[] = new int[7];
    static boolean ckEnd = false;
    
    public static void main(String[] args) throws IOException {
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        // 난쟁이들의 키 입력
        for (int i = 0; i < N; i++) 
            child[i] = Integer.parseInt(br.readLine());
        
        process(0, 0, 0);
    }
    /**
     * 일곱 난쟁이를 뽑을 수 있는 모든 경우의 수
     * @param idx 난쟁이의 위치
     * @param cnt 뽑은 난쟁이의 수
     * @param sum 뽑힌 난쟁이들 키의 합
     */
    public static void process(int idx, int cnt, int sum) {
        // 키의 합이 100인 일곱 난쟁이가 다 뽑힌 상태면
        // 더이상 경우의 수를 확인할 필요가 없으므로 return
        if(ckEnd) return;
        // 일곱 난쟁이가 뽑히면
        if(cnt == 7) {
            // 뽑힌 난쟁이들의 키의 합이 100이 되는지 확인
            if(sum == K) {
                // 키의 합이 100이라면 난쟁이들의 키를 오름차순으로 정렬 후 출력
                Arrays.sort(realChild);
                for (int i = 0; i < 7; i++) 
                    System.out.println(realChild[i]);
                ckEnd = true;
            }
            return;
        }
        if(idx >= N) return;
        // 일곱 난쟁이가 뽑히기도 전에 키의 합이 100을 초과하면 return
        if(sum > K) return;
        
        // 이 난쟁이가 진짜? 한번 뽑아볼까?
        realChild[cnt] = child[idx];
        process(idx + 1, cnt + 1, sum + child[idx]);
        // 이 난쟁이는 안 뽑고 넘어갈래
        process(idx + 1, cnt, sum);
    }
    
}



서로 다른 난쟁이를 for문으로 표현

import java.util.*;
import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int[] arr = new int[9];
        int sum = 0;
        for (int i = 0; i < 9; i++) {
            arr[i] = Integer.parseInt(br.readLine());
            sum += arr[i];
        }
        for (int i = 0; i < 8; i++) {
            for (int j = i+1; j < 9; j++) {
                if (sum - arr[i] - arr[j] == 100) {
                    arr[i] = 0;
                    arr[j] = 0;
                    Arrays.sort(arr);
                    for (int k = 2; k < 9; k++) {
                        System.out.println(arr[k]);
                    }
                    return;
                }
            }
        }
    }
}

코드 리뷰

가짜 난쟁이의 값을 제외시킬 때 나는 두 쌍의 난쟁이가 아니면 StringBuilder에 넣었는데 다른 분 중에 continue를 써서 제외시킨(건너띄다) 경우도 있었다.

 

profile

SIU

@웹 개발자 SIU

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!