카테고리 없음

[Baekjoon] 11055번: 가장 큰 부분 증가 수열 / dynamic

수기 2022. 3. 31. 20:06

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

 

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

수열 A가 주어졌을 때, 그 수열의 증가 부분 수열 중에서 합이 가장 큰 것을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8} 인 경우에 합이 가장 큰 증가 부분 수

www.acmicpc.net

sum배열에는 LIS[i]보다 작은 LIS[j]이면서, sum[j] + LIS[i] 값이 기존 sum[i]보다 클때 sum[i]를 갱신한다.
dp배열에서는 이전 dp값과 업데이트된 sum값중 큰 값을 저장한다.
배열의 1번째부터 시작했으므로 dp[n]번째 저장된 값이 LIS값이다.
예시를 예로 들면,

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10]
1 100 2 50 60 3 5 6 7 8

sum     dp  

[1] 1 1 -> sum, dp의 초기값은 LIS[1]
[2] 101 101 -> sum[1] + LIS[2] = 101 이므로 sum = 101
[3] 3 101 -> sum[1] + LIS[3] = 3 이므로 sum = 3, (LIS[2] > LIS[3] 이므로 sum[2]+LIS[3]는 X)
[4] 53 101 -> sum[3] + LIS[4] = 53
[5] 113 113 -> sum[4] + LIS[5] = 113
[6] 6 113 -> sum[3] + LIS[6] = 6
[7] 11 113 -> sum[6] + LIS[7] = 11
[8] 17 113 -> sum[7] + LIS[8] = 17
[9] 24 113 -> sum[8] + LIS[9] = 24
[10] 32 113 -> sum[9] + LIS[10] = 32

즉, LIS[i]보다 작은 LIS[j]일때의 sum[j]만 보고 LIS[j]와의 값이 가장 클때를 본다.
LIS[i]보다 LIS[j]가 작아야 증가하는 수열이 될 수 있음, LIS[i]보다 LIS[j]가 큰 경우, sum[j]는 더 큰 LIS[j]가 포함된 경우이므로 증가하는 수열이 아님

코드

//11055
#include <iostream>
using namespace std;
#define SIZE 1001

int MAX(int a, int b){
    if(a>b)return a;
    else return b;
}

int main(int argc, const char * argv[]) {
    cin.tie(NULL);
    ios::sync_with_stdio(0);
    
    int n;
    int LIS[SIZE]={0,};
    int sum[SIZE]={0,}; //임시 값
    int dp[SIZE]={0,}; //최고값 저장
    
    cin >> n;
    for(int i=1;i<=n;i++) cin >> LIS[i];
    
    for(int i=1;i<=n;i++){
        
        sum[i] = LIS[i];
        for(int j=1;j<=i;j++){
            if(LIS[j] < LIS[i] && sum[i] < sum[j] + LIS[i]){
                sum[i] = sum[j] + LIS[i];
            }
        }
        
        dp[i] = MAX(dp[i-1], sum[i]);
    }
    
    cout << dp[n];
   return 0;
}