문제 링크 : https://www.acmicpc.net/problem/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의 합이 가장 큰 증가 부분 수열의 합을 출력한다. 예제 입력 110 1 100 2 50 60 3 5 6 7 8 예제 출력 1113 |
[ 문제 풀이 ]
D[i] = A[i]가 마지막으로 오는 증가 부분 수열 중 가장 큰 합
D[1] = A[1]
D[2] = max(A[2], D[1] + A[2] if A[1] < A[2])
D[3] = max(A[3], D[1] + A[3] if A[1] < A[3], D[2] + A[3] if A[2] < A[3])
...
D[i] = max(D[j] + A[i], if j < i and A[j] < A[i])
ex) D[4] 구하기
D[j]는 A[j]를 반드시 사용하여(A[j]가 마지막으로 오게된다) 만드는 증가 부분 수열 중 가장 큰 합을 저장하고 있다.
[ 최종 구현(C++) ]
#include <stdio.h> #define MAX_NUMBER 1002 #define MAX(a,b) ((a) > (b) ? (a) : (b)) int A[MAX_NUMBER] = { 0, }; int D[MAX_NUMBER] = { 0, }; int main(void) { int N; int result = 0; scanf("%d", &N); for (register int i = 1; i <= N; i++) scanf("%d", &A[i]); D[1] = A[1]; for (register int i = 2; i <= N; i++) { D[i] = A[i]; for (register int j = 1; j <= i - 1; j++) { if (A[j] < A[i]) D[i] = MAX(D[i], D[j] + A[i]); } } for (register int i = 1; i <= N; i++) { result = MAX(result, D[i]); } printf("%d\n", result); return 0; }
'Algorithm > 문제풀이' 카테고리의 다른 글
[다이나믹 프로그래밍] 가장 긴 바이토닉 부분 수열 (0) | 2018.08.11 |
---|---|
[다이나믹 프로그래밍] 가장 긴 감소하는 부분 수열 (0) | 2018.08.11 |
[다이나믹 프로그래밍] 가장 긴 증가하는 부분 수열 (0) | 2018.08.10 |
[다이나믹 프로그래밍] 포도주 시식 (0) | 2018.08.10 |
[다이나믹 프로그래밍] 스티커 (0) | 2018.08.07 |