• [백준 알고리즘] (DP) 11055번 Java풀이

    2020. 3. 27.

    by. SDev

    728x90

     

     

    만약 이 문제 전에 11053번 문제를 안풀어봤다면 먼저 풀어보고 오기를 추천한다.

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

     

     

    DP - 1463, 11726, 11727, 9095, 10844, 11057, 2193, 9465, 2156, 11053, 11055, 11722, 11054, 1912, 2579, 1699, 2133, 9461, 2225, 2011, 11052

    출처: https://plzrun.tistory.com/entry/알고리즘-문제풀이PS-시작하기 [plzrun's algorithm]

     

    알고리즘 문제풀이(PS) 시작하기

    이런건 고수들이나 써야 하지 않나 싶지만, 그래도 1년정도 공부하면서 이 분야를 어떻게 시작해야 할지 써보려 한다. 라고 운을 뗀다음 열심히 내 얘기만 했던 후속편이다. 내 인생사가 궁금하신 분들은 이 글의..

    plzrun.tistory.com

     

    백준 알고리즘 11055번

     

    <첫 번째 오답 풀이>

    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
    40
    41
    42
    43
    44
    45
    package dp;
     
    import java.util.Scanner;
     
    public class N11055 {
     
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            int arr[] = new int[n+1];
            int dp[] = new int[n+1];
            int sum[] = new int[n+1];
            
            for(int i=1; i<=n; i++) {
                arr[i] = sc.nextInt();
            }
            sc.close();
            for(int i=1; i<=n; i++) {
                dp[i] = 1;
            }
            for(int i=1; i<=n; i++) {
                sum[i] = arr[i];
            }
            
            for(int i=2; i<=n; i++) {
                for(int j=1; j<i; j++) {
                    if(arr[j]<arr[i] && dp[i]<=dp[j]) {
                        dp[i] = dp[j]+1;
                    }
                    if(dp[i]>dp[j] && arr[i]>arr[j]) {
                        sum[i] = sum[j]+arr[i];
                        
                    }
                }
            }
            
            int max =0;
            for(int i=1; i<=n; i++) {
                max = Math.max(max, sum[i]);
            }
            System.out.println(max);
        }
     
    }
     
    Colored by Color Scripter
     

     

    풀이 접근법은 이전에 풀었던 11053번에서 딱 하나 추가했다.

    dp[]로 증가하는 배열을 골라내고, sum[]으로 각 위치에서의 최대 증가부분배열의 합을 구하는 것이다.

    sum[]을 모두 구하고 나서, 배열 전체에서 최댓값을 출력하면 끝!!

     

    주어지는 예제 입력인 {1, 100, 2 ,50, 60, 3, 5, 6, 7, 8}에서 출력값 113을 잘 출력해낸다.

    그러나 결과는 ........ 오답!

    그리고 왜 이 풀이가 틀렸는지 임의로 내가 테스트케이스를 만들어보며 문제를 찾을 수 있었다.

     

     

    <정답 풀이>

    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
    40
    41
    42
    43
    44
    45
    package dp;
     
    import java.util.Scanner;
     
    public class N11055 {
     
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            int arr[] = new int[n+1];
            int dp[] = new int[n+1];
            int sum[] = new int[n+1];
            
            for(int i=1; i<=n; i++) {
                arr[i] = sc.nextInt();
            }
            sc.close();
            for(int i=1; i<=n; i++) {
                dp[i] = 1;
            }
            for(int i=1; i<=n; i++) {
                sum[i] = arr[i];
            }
            
            for(int i=2; i<=n; i++) {
                for(int j=1; j<i; j++) {
                    if(arr[j]<arr[i] && dp[i]<=dp[j]) {
                        dp[i] = dp[j]+1;
                    }
                    if(dp[i]>dp[j] && arr[i]>arr[j]) {
                        if(sum[i]< sum[j]+arr[i]) {
                            sum[i] = sum[j]+arr[i];
                        }
                    }
                }
            }
            
            int max =0;
            for(int i=1; i<=n; i++) {
                max = Math.max(max, sum[i]);
            }
            System.out.println(max);
        }
     
    }
    Colored by Color Scripter
     

     

    이전 풀이와 정답 풀이의 차이는 정답 풀이 내 31라인 단 한줄이다.

    만약 이 부분이 없었다면 발생할 수 있는 문제는 다음과 같다.

    다음과 같이 입력이 {3, 4, 7, 5, 8, 11, 19, 15, 8}로 크기가 9인 배열이 주어지는 경우를 생각해보자.

    이전 풀이로 풀게되면
    Arr[5]인 8에서(i는 1부터 시작으로 가정) sum이 20이 나온다. 
    i=5 j=3인 상황에서 sum = 22이 나오는데, 이후 j=4인 경우에서 sum이 더 작은 20으로 바뀌어 버린다.

    따라서, sum의 값을 업데이트하기 전에,
    업데이트 할 sum의 값이 만약 이전 값보다 작다면 업데이트를 못하게 막는 31라인을 추가한 것이다.

     

     

    결과는 성공!! 에러 없이 정답 결과를 받을 수 있었다.

     

     

    Github: https://github.com/jaeuk9407/AlgorithmBOJ

     

    jaeuk9407/AlgorithmBOJ

    BaekJoon Online Judge Problems. Contribute to jaeuk9407/AlgorithmBOJ development by creating an account on GitHub.

    github.com

     

    댓글