본문 바로가기
PS

백준 1912번 C++ 연속합

by mtoc 2019. 5. 30.


연속합

https://www.acmicpc.net/problem/1912

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

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





생각하는 과정

이 문제에서 생각해 볼 수 있는 케이스는 연속일 때만을 고려하므로, 두 가지다.

i번째를 선택한다는 가정하에

1) 연속이 아닐때(i-1번째를 선택하지 않을 때) -> dp[i] 선택(자기 자신만을 가지고 감)

2) 연속일 때(i-1번째를 선택할 때) -> dp[i-1]+series[i] 선택(자기 자신보다 그 전의 연속합에 자기 자신을 더한 것이 더 큼)


예제에서 생각해보자. 연속합이 최대여야 한다.

10, -4, 3, 1, 5, 6, -35, 12, 21, -1

0번째에서 최대합은 10 하나뿐이므로 10이다.

1번째에서 최대합은 -4<10-4이므로 6이다. 

2번째에서 최대합은 3<6+3이므로 9이다.

3번째에서 최대합은 1<9+1이므로 10이다.

4번째에서 최대합은 5<10+5이므로 15이다.

5번째에서 최대합은 6<15+6이므로 21이다.

6번째에서 최대합은 -35<21-35이므로 -14이다.

7번째에서 최대합은 12>12-14이므로 12이다. <-끊기는 지점

8번째에서 최대합은 21<12+21이므로 33이다.

9번째에서 최대합은 -1<33-1이므로 32이다.

마지막으로 이 중에서 최대를 고르면 33이다.

이 문제에서 0번째 인덱스를 고려해주지 않아도 되는 이유는 0번째 인덱스를 선택하든 말든 중간이 끊기지 않고

수열의 최대합을 구하는 게 아니라 '연속하는' 최대합을 구하는 것이기 때문이다.

0번째 인덱스를 선택하는 것보다 어느 지점에서 어느 지점까지를 연속합으로 택하느냐가 총합을 결정짓는다. 





코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#define MAX 100001
using namespace std;
int series[MAX], dp[MAX]={0,};
int main() {
    int n, i;
    cin>>n;
    for(i=0; i<n; i++) {
        cin>>series[i];
        dp[i]=series[i];
    }
    int maxSum=dp[0];
    for(i=1; i<n; i++) {
        dp[i]=max(dp[i], dp[i-1]+series[i]);
        if(dp[i]>maxSum) {
            maxSum=dp[i];
        }
    }
    cout<<maxSum<<endl;
    return 0;
}
cs





결과

아마 생각하고 풀었으면 틀렸을 것이다...

꾸준하게 하자

'PS' 카테고리의 다른 글

백준 2225번 C++ 합분해  (0) 2019.06.02
백준 9461번 C++ 파도반 수열  (0) 2019.06.01
백준 1015번 C++ 수열 정렬  (0) 2019.05.29
백준 2133번 C++ 타일 채우기  (0) 2019.05.28
백준 1699번 C++ 제곱수의 합  (0) 2019.05.28

댓글