https://www.acmicpc.net/problem/1912
원트에 풀었지만 다시 생각해보니 생각해볼 만한 점이 있어 포스팅한다.
처음에 생각한 점화식은
이번에 들어가야 할 값 = max(이전까지의 연속합+현재값, 현재값, 현재값+바로 이전 값)
이었다.
왜 현재 값+바로 이전 값을 계산해야 된다고 생각했는지는 잘 모르겠다.
무조건 2개를 선택해서 연속합을 만들어야 한다면, 그렇게 될 것 같다.
하지만 문제에서는 1개 이상만 선택하면 된다고 했으니, 점화식은
이번 연속합 = max(바로 이전까지의 연속합+현재값, 현재값) 이 된다.
이 뜻은,
현재 값에 연속합을 더하는 것이 낫냐? 아니면 이전 연속합을 더하는게 손해냐? 를 묻는 것이다.
예를 들어 주어진 수열이 -1, -1, 55 이라고 생각할 때,
연속합+현재값은 53이고 현재 값은 55이므로 최대 연속합은 55이다.
이전 연속합들을 데리고 갈지, 아니면 더하면 오히려 손해이므로 버리고 갈 지를 결정한다고 생각하면 된다.
주석친 곳을 보면
maxSum = max(seq[now]+subsum[now-1], seq[now]) 라고 되어 있는데, 이것이 볼드처리한 점화식과 같다.
seq는 주어진 수열, subsum은 연속합을 저장한 배열이다.
하지만 이 max 를 보면, seq[now]가 양쪽에 공통되어 있다는 사실을 알 수 있는데.
그렇다면 max(subsum[now-1], 0)이 된다.
이것을 풀어서 생각해보면
이전까지의 연속합이 0을 넘느냐? 이다.
이전까지의 연속합이 0을 넘으면, 현재 값이 양수든 음수든 무조건 더하는게 이득이므로 데리고 간다. 라는 뜻이다.
그래서 본문과 같이 if문으로 바꿔봤더니 속도가 더 빨라졌다.
import sys
N = int(sys.stdin.readline())
seq = list(map(int, sys.stdin.readline().split())) # 주어진 수열
subsum = [seq[0]] # 연속합을 저장할 리스트
for now in range(1, N):
# 연속 합에 현재 값을 더하는 게 낫냐? OR 현재 값에서 다시 시작하는 게 낫냐?
#maxSum = max(seq[now]+subsum[now-1], seq[now])
#subsum.append(maxSum)
if subsum[now-1] > 0:
subsum.append(seq[now] + subsum[now-1])
else:
subsum.append(seq[now])
print(max(subsum))
'알고리즘 > 동적프로그래밍' 카테고리의 다른 글
14501번. 퇴사 (DP) (0) | 2020.04.17 |
---|---|
12865번. 평범한 배낭 (0) | 2019.12.06 |
2565번. 전깃줄 (0) | 2019.12.05 |
11054번. 가장 긴 바이토닉 부분 수열 (0) | 2019.12.05 |
10844번. 쉬운 계단 수 (0) | 2019.12.04 |