티스토리 뷰

연속합 2 성공

 

13398번: 연속합 2

첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

www.acmicpc.net

문제

n개의 정수로 이루어진 임의의 수열이 주어진다. 우리는 이 중 연속된 몇 개의 수를 선택해서 구할 수 있는 합 중 가장 큰 합을 구하려고 한다. 단, 수는 한 개 이상 선택해야 한다. 또, 수열에서 수를 하나 제거할 수 있다. (제거하지 않아도 된다)

예를 들어서 10, -4, 3, 1, 5, 6, -35, 12, 21, -1 이라는 수열이 주어졌다고 하자. 여기서 수를 제거하지 않았을 때의 정답은 12+21인 33이 정답이 된다.

만약, -35를 제거한다면, 수열은 10, -4, 3, 1, 5, 6, 12, 21, -1이 되고, 여기서 정답은 10-4+3+1+5+6+12+21인 54가 된다.

입력

첫째 줄에 정수 n(1 ≤ n ≤ 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.

출력

첫째 줄에 답을 출력한다.

 

 

내 코드

import sys
n=int(sys.stdin.readline())
arr=list(map(int,sys.stdin.readline().split()))

dp=[[[]for _ in range(n)]for _ in range(2)]

#첫번째 수만 있을 때는 항상 선택해야 된다. (dp[][0] 초기화)
dp[0][0]=arr[0]
dp[1][0]=arr[0]


for i in range(1,n):
    dp[0][i]=max(dp[0][i-1]+arr[i],arr[i]) #dp[0][x]: 아직 수를 안 뺀 상태
    dp[1][i]=max(dp[0][i-1],dp[1][i-1]+arr[i]) #dp[1][x]: 수를 어딘가에서 뺀 상태

for x in dp:
    print(x)

print(max(max(dp[0]),max(dp[1]))) #빼기 vs 안 빼기

 

 

풀이 및 접근)

- n이 최대가 100,000이므로 모든 경우를 다 더해보면 시간 초과가 나게 된다. 그래서 바로 누적 합의 아이디어를 떠올렸다.

 

- 그리고서는 처음 수부터 추가해 나가면서, 이전에 뺐을 때 or 안 을 때를 나누어서 최대값을 최신화 시켜나갔다. 하지만 초기설정과 안 을 때 업데이트 하는 과정이 약간 틀렸었다.

 

- dp[0][ ]에는 빼지 않았을 때의 값을 업데이트 하고, dp[1][ ]에는 을 때의 값을 업데이트 한다.

 

 

- dp[0][ ]의 값이 세팅되는 과정은 다음과 같다.

 

    1. 이전 단계에서 빼지 않았을 때의 값 + 현재 숫자

    2. 현재 숫자 단독으로 다시 시작

 

-둘 중 큰 값으로 세팅해 준다. dp[0][ ]에는 빼지 않았을 때의 상태들만 존재해야 하므로 절대로 현재 숫자를 빼거나, 이전에 던 상태를 들고오면 안된다.

- 2의 경우는, 만약 이전 단계에서 빼지 않았을 때의 값이 -999이고, 현재 숫자가 5라 하면, 이전의 합을 사용하지 않고 현재 숫자부터 다시 시작하는 편이 더 이득이다.

 

 

- dp[1][ ]의 값이 세팅되는 과정은 다음과 같다.

 

    1. 이전 단계에서 빼지 않았을 때의 값

    2. 이전 단계에서 을 때 + 현재 숫자

 

- 둘 중 큰 값으로 세팅해 준다. dp[1][ ]에는 뺐을 때의 상태가 존재한다. 이는 (이전에 안뺌+지금 뺌) or (이전에 뺌+지금 안 뺌) 의 경우들이다.

 

 

- 이런 식으로 값들을 업데이트 하면, 각각의 순간들에 대해 최대값들이 dp 배열에 들어가 있을 것이다. 최종 답은, 하나를 뺐을 때의 최대가 더 큰 지, 빼지 않았을 때의 최대가 더 큰 지를 비교해주면 된다.

 

- 헷갈리거나 주의해야 할 점들은, dp가 숫자가 한 개 있을 때부터 시작하게 되는데, 적어도 한 개의 숫자를 선택해야 하므로 dp[0][0]과 dp[1][0]의 값 모두 첫번째 숫자로 세팅한다. 또한, dp[0][ ]에서 현재 숫자부터 다시 시작하는 경우도 고려해야 하는 것 또한 중요하다.

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
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
글 보관함