Updated:

1. 문제 풀이 방법

하나의 수열을 전체로 생각했을 때 조가 잘 짜여진 정도가 큰 지 아니면 나눠서 생각했을 때 조가 잘 짜여진 정도가 큰 지를 비교해서 더 큰 값을 저장하는 방식으로 memoization을 구현해서 풀었다.

이를 간단하게 표현하면 아래와 같다.

  • $S_n: \text{score of n-th student ordered by age}$
  • $dp[i] = \underset{ 0\le j \lt i}{max} \bigg(dp[j] + max(S_{j+1},\cdots, S_i ) - min(S_{j+1}, \cdots,S_i)\bigg)$

Python에 내장된 max 함수와 min함수의 시간 복잡도가 $O(n)$이기 때문에 max 함수와 min함수를 그대로 사용할 경우 $O(n^3)$이 되어 시간 초과가 발생한다.

미리 다른 배열을 통해 $max(S_{j+1},\cdots, S_i ) - min(S_{j+1},\cdots,S_i)$ 값을 구하여서 최종적으로 $O(n^2)$ 알고리즘을 구현해내었다.

오랜만에 동적계획법 문제를 푸는 것도 있고 시간초과가 발생하지않게 알고리즘을 만드는 것도 있고 해서 난이도에 비해 시간이 오래 걸렸다.

2. 풀이

import sys
def input(): return sys.stdin.readline().rstrip()

n = int(input())
scores = list(map(int,input().split()))

# diff[i][j]: scores[j:i+1]의 최댓값과 최솟값의 차이
diff = [[0] * n for _ in range(n)]
for i in range(n):
    max_n, min_n = -1,1e10
    for j in range(i,-1,-1):
        if max_n < scores[j]: max_n = scores[j]
        if min_n > scores[j]: min_n = scores[j]
        diff[i][j] = max_n - min_n
        
dp = [0] * n
max_n, min_n = -1,1e10
for i in range(n):
    if scores[i] > max_n: max_n = scores[i]
    if scores[i] < min_n: min_n = scores[i]
    dp[i] = max_n - min_n
    for j in range(i):
        if dp[i] < dp[j] + diff[i][j+1]:
            dp[i] = dp[j] + diff[i][j+1]
print(dp[n-1])

Leave a comment