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




풀이


수열 중 가장 긴 증가하는 부분 수열을 구하면 된다.

arr[1] ... arr[n-1], arr[n]까지 총 n개의 수열이 주어진다고 할 때


dp[n] 을 이용해서 n번째 수열까지의 부분수열의 최대값을 저장하려고 한다.


1번째로 세워야할 조건


arr[n] > arr[n-1] 인가? 아니라면 증가하는 부분 수열이라고 할 수 없기 때문이다.

arr[i]를 마지막 배열이라고 가정 했을 때 수열의 최대 길이를 dp[i]라고 한다. 그러면  최대 dp[i]를 구하기 위해서 

arr[1], arr[2], arr[3] ... arr[i-1]까지 arr[i]보다 작은수가 존재하지 않는다면 dp[n]은 1이 될 것이다.

만약 arr[3]까지의 증가하는 부분수열의 최대길이인 dp[3]이 2라고 하고

arr[4]가 arr[3]의 값보다 크지 않다면 dp[4]는 2가 될것이다.


위의 조건과 예시를 종합해 조건식을 만들자면 아래와 같은 식이 나온다.

for(int i = 1; i <= N; i++){

for(int j = 1; j < i; j++}{

if(arr[j]< arr[i]) dp[i] = dp[j] + 1;

}

}


하지만 빠진 조건이 하나 존재한다. 우리는 부분수열의 최대길이를 구해야하지만  위의 식대로 프로그램을 돌리면 위의 조건문을 만족하는 i 와 가장 가까운 j 의 부분수열의 최대길이가 dp[i]에 대입되기 때문에 아래 예시와 같은 예외의 경우가 나타나게 된다.

ex) 

2    3    4    1    5

    dp[i]    1    2    3    1    ? <<-- dp[5]는 4가 되어야 하지만 dp[5] = dp[4] + 1; 로 인해 2가 되어 버릴 것이다. 그래서 아래와 같은 조건 하나를 추가한다.

if(dp[i] < dp[j] + 1) dp[i] = dp[j] +1;



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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
#define Max(a,b) a>b ? a:b
 
 int main() {
    int N;
    int arr[1001= { 0 };
    int dp[1001= { 0 };
    int max = 0;
    scanf("%d"&N);
 
    for (int i = 1; i <= N; i++) {
        scanf("%d"&arr[i]);
    }
 
    
 
    for (int i = 1; i <= N; i++){
        dp[i] = 1;
        for (int j = 1; j < i; j++) {
            if (arr[i] > arr[j]) {
                if(dp[i] < dp[j] +1)    dp[i] = dp[j] + 1;
            }
        }
            max = Max(dp[i], max);
    }
    
    printf("%d", max);
 
    return 0;
 
}
cs


'알고리즘' 카테고리의 다른 글

(1010)(DP) 백준 다리놓기  (0) 2018.07.15
(11727)(DP) 백준 2xn 타일링 2  (0) 2018.07.15
(11052)(DP) 백준 붕어빵 판매하기  (0) 2018.07.14
(10844)(DP) 백준 쉬운 계단 수  (0) 2018.07.13
(1912)(DP) 백준 연속합  (0) 2018.07.12

+ Recent posts