ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 10610] - [그리디알고리즘] - 30 (JAVA)
    알고리즘/그리디알고리즘(Greedy Algorithm) 2018. 12. 27. 16:24

    문제 링크 : https://www.acmicpc.net/problem/10610



    이 문제는 그리디 알고리즘 문제 중에서 어려운 편에 속하는 문제이다. 


    문제 자체에 오해 할 수 있는 요소가 존재해서 다들 잘못 이해 하고 접근하다가 계속 틀리다는 결과를 받는거 같다.



    N을 입력받는다. N는 최대 105개의 숫자로 구성되어 있으며, 0으로 시작하지 않는다.


    입력값 은 최대 10^5 의 숫자라고 하는게 100000 까지 입력을 받는게 아니라 자리수가 10^5개라는 말이었다. 


    대부분의 사람들도 100000 까지만 입력 받는걸로 이해하고 문제를  접근해서 고생을 한 거 같다. 


    정수형 타입인 int 나 실수형 타입인 long 이나 10^5개의 자리수를 입력 받을 수 있는  자료형은 없다.


    그럼 어떻게 문제를 풀어야 할까? 


    입력 자체를 문자열 타입으로 받으면 문제는 해결된다. 


    999999999900000000000000000999999999999999999 의 숫자를 입력 받았을경우 절때 int 나 long으로는 값을 입력받을 수 없기 때문이다. 


    문자열로 입력을 받은 뒤에 Substring으로 각 자리수를 잘라가면서 0부터 9까지 각 숫자가 몇개로 조합됐는지 확인한다.



    strLen = str.length();

    numCountArr = new int[10];

    long total = 0;

    for(int i=0; i < strLen; i++) {

    int tNum = Integer.parseInt(str.substring(i, i+1));

    numCountArr[tNum] += 1;

    total+=tNum;

    } 



    입력을 받았다면 입력받은 데이터가 유효한 숫자인지 확인하면 된다. 


    30의 배수인지 확인하는 방법은 어떻게 될까?


    조건 1) 0 이 있어야 한다.


    30의 배수는 무조건 뒤에 최소한 한개 이상의 0을 가지고 있다. 

    입력 받은 수 자체에 0이 존재하지 않다면? 그 수는 유효하지 않은 수이기 때문에 -1을 출력해주고 프로세스를 종료시키면 된다.


    조건 2) 각 자리수의 합이 3의 배수여야 한다.


    이 조건은 이해하기가 힘든데 3의 배수를 표로 그려서 확인해보면 이해하기 쉽다. 


    3 * 1

    3 * 11

    33 

    3 * 2

    3 * 12 

    36 

    3 * 3

    3 * 13 

    39 

    3 * 4 

    12 

    3 * 14 

    42 

    3 * 5 

    15 

    3 * 15 

    45 

    3 * 6 

    18 

    3 * 16 

    48 

    3 * 7 

    21 

    3 * 17 

    51 

    3 * 8 

    24 

    3 * 18 

    54 

    3 * 9 

    27 

    3 * 19 

    57 

    3 * 10 

    30 

    3 * 20 

    60 


    위의 표는 3의 배수를 60까지 구해본 표이다.


    각 3의 배수의 결과들의 모든 자리수를 더해보면 그 수들 또한 3의 배수이다. 



    // 0이 존재하지 않으면 30 배수 조차도 될 수 없다.

    // 각 자리수의 총 합이 3의 배수가 아니면 종료해야한다.

    if(!str.contains("0") || total % 3 != 0) {

    System.out.println("-1");

    return;

    } 


    그렇다면 조건 1과 조건 2를 모두 만족한다면 입력 받은 수는 30의 배수가 될 수 있다는 말이다. 


    입력값에 대한 0부터 9 까지의 각 숫자의 개수를 가지고있는 배열을 9부터 0까지 전부 문자열에 합해주면 결과를 출력할 수 있다.


    StringBuilder sb = new StringBuilder();

    for(int i = 9; i >= 0; i--) {

    while(numCountArr[i] > 0) {

    sb.append(i);

    numCountArr[i]--;

    }

    } 



    소스

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    import java.util.Scanner;
     
    public class Main {
        public static final int MAX = 100000;
        
        public static String str;
        public static int[] numCountArr;
        public static long strLen;
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            str= sc.nextLine();
            
            strLen = str.length();
            numCountArr = new int[10];
            long total = 0;
            for(int i=0; i < strLen; i++) {
                int tNum = Integer.parseInt(str.substring(i, i+1));
                numCountArr[tNum] += 1;
                total+=tNum;
            }
            
            // 0이 존재하지 않으면 30 배수 조차도 될 수 없다.
            // 각 자리수의 총 합이 3의 배수가 아니면 종료해야한다.
            if(!str.contains("0"|| total % 3 != 0) {
                System.out.println("-1");
                return;
            }
            
            StringBuilder sb = new StringBuilder();
            for(int i = 9; i >= 0; i--) {
                while(numCountArr[i] > 0) {
                    sb.append(i);
                    numCountArr[i]--;
                }
            }
            System.out.println(sb.toString());
        }
    }
     
    cs



    댓글

Designed by Tistory.