룰루랄라 코딩기록장

[Baekjoon] 백준 11055번 가장 큰 증가하는 부분수열 본문

Algorithm/다이나믹프로그래밍

[Baekjoon] 백준 11055번 가장 큰 증가하는 부분수열

Jeonnnng 2019. 6. 5. 16:42

11055번 가장 큰 증가하는 부분수열 문제 풀이

문제

  • 수열 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의 합이 가장 큰 증가 부분 수열의 합을 출력한다.

예제

입력
10
1 100 2 50 60 3 5 6 7 8 
출력
113

코드

#include<iostream>
#include<algorithm>
using namespace std;

int a[1001];
int d[1001];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        d[i] = a[i];
        for (int j = 0; j < i; j++) {
            if (a[j] < a[i] && d[i] < d[j] + a[i]) {
                d[i] = d[j] + a[i];
            }
        }
    }
    int ans = 0;
    for (int i = 0; i < n; i++) {
        if (ans < d[i])
            ans = d[i];
    }
    cout << ans << '\n';
    return 0;

해결방법

  • 가장 긴 증가하는 부분수열 문제와 풀이방식은 동일하며, 코드도 몇 군데만 고쳐주면 바로 해결된다.

      for (int i = 0; i < n; i++) {
          d[i] = a[i];
          for (int j = 0; j < i; j++) {
              if (a[j] < a[i] && d[i] < d[j] + a[i]) {
                  d[i] = d[j] + a[i];
              }
          }
      }
  • 가장 긴 문제에서 d[i]는 항상 1을 가졌던 것 처럼, 가장 큰 문제에서는 a[i]값, 즉 자기 자신이 가징 가중치를 기본적으로 갖는다.

  • if문에서 본인 위치보다 이전에 있는 위치의 가중치가 작고, d[i] 즉 a[i]를 마지막으로 하는 수열의 가중치들의 합이 이전 위치에서 나온 가중치의 합 + 본인 가중치보다 작을 경우 d[i] = d[j] + a[i]가 된다.

  • 말로 구구절절하게 설명하였지만 그냥 가장 긴 문제에서 본인 위치에 대해 +1해준것 을 +a[i]했다고 생각하면 쉽게 풀이할 수 있다.

Comments