연속합
1912_연속합의 응용 문제다.
먼저 1912번부터 살펴보자.
dp를 활용해서 풀 것이다. dp에 처음 숫자부터, 해당 숫자까지 연속된 수의 최대합을 저장한다.
dp[i]에 연속된 수의 최대합을 저장하는 과정을 다시 잘게 쪼개보면,
- dpi-1 + num[i]
- num[i]
둘중 한가지가 dpi임을 알 수 있다.
예시를 들어서 부연 설명을 해보자. 10 -4 3 이렇게 세 숫자가 있다.
- dp[0] = 10 (수는 한 개 이상 선택해야 함으로)
- dp[1] = max(10-4,10) = 6
이제 dp[2]를 구해보자.
- 3 하나를 선택할 수 있다.
- -4 를 선택하면, 10도 같이 선택하는게 연속합을 더 크게 만든다.
이런식으로 왼쪽의 수들을 더하기로 결정하는 과정에서 이 수들을 더했을 때, 나에게 +가 되는지 -가 되는지 판단하는 것이다. 이것을 위의 식으로 표현하면, max(dp[i-1] + num[i], num[i])가 된다.
dp[i] = max(dp[i-1] + num[i], num[i])
CODE - 연속합
import sys
read = sys.stdin.readline
n = int(input())
num = list(map(int, read().split()))
dp = list(0 for _ in range(n))
dp[0] = num[0]
for i in range(1, n):
dp[i] = max(num[i], dp[i-1]+num[i])
print(max(dp))
연속합2
위의 문제에서 한개의 수를 뺄 수 있는 찬스가 주어지는 문제이다. dp점화식을 조금만 수정해주면 쉽게 풀 수 있다.
우선, 한개의 수를 제거했는지 제거하지 않았는지 판단해야 하기 때문에, dp[i]=[,] 이렇게 dp각각의 원소에 두가지 값을 저장하기로 했다.
dp[i][0]에는 i까지의 숫자 중 제거한 숫자가 없을 때의 최대 연속합을 저장한다. 연속합에서 구한 방식과 정확히 일치한다.
dp[i][1]에는 아래의 세가지 경우 중 가장 큰 값을 저장한다.
- dp[i][0] (숫자를 제거하지 않고 연속합을 구하는 경우)
- dp[i-1][0] (i번째 숫자를 제거하는 경우)
- dp[i-1][1]+num[i] (이미 i번째 이전의 숫자가 제거되어 i번째 숫자는 반드시 더해야 하는 경우)
점화식:
dp[i][0] = max(num[i], dp[i-1][0]+num[i])
dp[i][1] = max(dp[i][0], dp[i-1][0], dp[i-1][1]+num[i])
CODE - 연속합 2
import sys
read = sys.stdin.readline
n = int(read())
num = list(map(int, read().split()))
dp = list([0, 0] for _ in range(n))
dp[0] = [num[0], num[0]]
answer = num[0]
for i in range(1, n):
dp[i][0] = max(num[i], dp[i-1][0]+num[i])
dp[i][1] = max(dp[i][0], dp[i-1][0], dp[i-1][1]+num[i])
answer = max(answer, dp[i][1])
print(answer)
틀린 부분이 있을 수 있습니다. 피드백 주시면 고치도록 하겠습니다! 감사합니다.👍
[꼭 다시 풀어보기]