코딩 테스트(Coding Test)/백준

[백준 18511번] 큰 수 구성하기

배씌 2024. 12. 11. 18:16

https://www.acmicpc.net/problem/18511


문제


아이디어

초기에는 입력받은 N의 각 자릿수와 K의 원소를 비교하며 순차적으로 탐색했다. 하지만, 이 방법으로 구현하게되면 N을 문자열로 변환하여 계산하기에 아래와 같은 입력에서 제대로된 값을 얻을 수 없다.

4311 3
4 8 9

 

위 입력을 받았을 때, 각 자릿수와 순차적으로 비교하면 맨 앞자리인 '4'와 K의 원소 '4'를 대응시키게 되는데, 이는 우리가 원하는 답이 아니다. 우리는 위 상황에서 최대로 만들 수 있는 수가 '999' 인 것을 알기에 다른 방법을 생각해야했다.

 

두번째 방법은 K의 원소로 만들 수 있는 모든 수를 구하고, 이의 최댓값을 찾는 것이다.

 

위 방법을 위해 dfs 를 사용하기로 했다. 

K의 원소를 노드로 생각하고, String 형태로 숫자를 하나씩 붙여가며 N보다 작은 모든 수를 찾는다.

 

아래와 같이 arr[] 에는 K의 원소들을 넣어두고, num에다가 하나씩 붙여 이를 N보다 작은 모든 수들에 대해 최댓값을 기록하면 된다.

for(int i=0; i<k; i++) {
    dfs(Integer.parseInt(num+"" + arr[i]+""));
}

 

위 코드는 이런 식으로 동작된다.

4311 3
4 8 9

dfs(4) -> dfs(44) -> dfs(444) -> dfs(4444) (N보다 크므로 return) -> dfs(4448) (N보다 크므로 return) -> ... dfs(448) -> ...

위 방법대로 진행하며 최댓값을 기록한다.


전체 코드

package Baekjoon;

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

public class B_18511 {
    static int n, k, max;
    static int[] arr;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        // N, K 입력
        n = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());

        // K원소 배열
        arr = new int[k];
        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < k; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }
        // K원소 배열 정렬
        Arrays.sort(arr);

        max = 0;
        dfs(0);
        System.out.println(max);
    }

    static void dfs(int num) {
        // num이 n보다 크면 리턴(스택에서 제거)
        if(num > n) return;

        max = Math.max(max, num);

        for(int i=0; i<k; i++) {
            dfs(Integer.parseInt(num+"" + arr[i]+""));
        }
    }
}