알고리즘 문제풀이

[BOJ] 11055번 - 가장 큰 증가 부분 수열 본문

자료구조 + 알고리즘/[BOJ]

[BOJ] 11055번 - 가장 큰 증가 부분 수열

JoonDev 2020. 11. 12. 15:02

11055번 - 가장 큰 증가 부분 수열

시간제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 256 MB 21376 9707 7712 45.706%

문제

수열 A가 주어졌을 때, 그 수열의 증가 부분 수열 중에서 합이 가장 큰 것을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8} 인 경우에 합이 가장 큰 증가 부분 수열은 A = {1, 100,2,50,60, 3, 5, 6, 7, 8} 이고, 합은 113이다.


입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai≤ 1,000)


출력

첫째 줄에 수열 A의 합이 가장 큰 증가 부분 수열의 합을 출력한다.


예제 입력 1

10
1 100 2 50 60 3 5 6 7 8

예제 출력 1

113

출처

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

알고리즘 분류

  • LIS
  • DP

접근 방법

LIS 알고리즘의 응용편이다. LIS알고리즘에서는 길이를 기준으로 구한 반면, 문제에서는 증가하는 부분수열 중 합이 최댓값인 것을 구하라고 하였다.
우리는 $DP[i]$를 arr[i]를 마지막으로 포함하는 증가부분수열 중 합이 가장 큰 것 으로 정의를 하면 LIS와 비슷한 방식의 점화식을 세울 수 있다.

  • $DP[i] = \begin{cases} DP[j] + arr[i] & \text{if (arr[j] < arr[i] and DP[j] + arr[i] > DP[i]) } \\ DP[i] & \text{if (arr[j] < arr[i] and DP[j]+ arr[i] <= DP[i]) } \end{cases}$

소스 코드

#include <iostream>
#include <vector>

using namespace std;
vector<int> DP;
int main(void){
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    int N;
    cin >> N;
    vector<int> arr(N);
    DP.resize(N);
    for(int i=0; i<N; i++){
        cin >> arr[i];
    }

    // DP[i] 를 i를 마지막으로 포함하는 증가부분수열중 합이 가장 큰 것.
    for(int i=0; i<N; i++){
        DP[i] = arr[i]; // 항상 자기 자신을 부분수열로 가짐.
        for(int j=0; j<i; j++){
            if( arr[j] < arr[i] && DP[j] + arr[i] > DP[i] )
                DP[i] = DP[j] + arr[i];
        }
    }

    int max = -1;
    for( auto it : DP ){
        if( it > max ){
            max = it;
        }
    }
    cout << max;

    return 0;
}

'자료구조 + 알고리즘 > [BOJ]' 카테고리의 다른 글

[BOJ] 1245번 - 농장 관리  (0) 2020.11.13
[BOJ] 11054번 - 가장 긴 바이토닉 부분 수열  (0) 2020.11.13
[BOJ] 2631번 - 줄 세우기  (0) 2020.11.12
[BOJ] 3190번 - 뱀  (0) 2020.11.12
[BOJ] 18119번 - 단어 암기  (0) 2020.11.11
Comments