[백준 1912] 연속 합 (DP, 점화식)

2022. 10. 24. 17:38·알고리즘

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

 

1912번: 연속합

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

www.acmicpc.net

임의의 수열에서 '연속'된 '몇개'의 수를 선택해서 구할 수 있는 합 중 가장 큰 값을 구하는 문제이다.

(최소 하나 이상 선택)

 

수열의 길이가 n이고

입력받은 수열을 배열 arr[100001]에 arr[1]부터 arr[n]까지 차례대로 입력받는다고 할 때, 

dp[100001]은 arr[i]를 끝값으로 가지는 연속된 수열합의 최대값을 저장한다.

 

첫번째 예제에서와 같이 입력받았을 경우를 살펴보자!

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

dp[1] = 10

dp[2] = 10 + (-4) = 6

dp[3] = 10 + (-4) + 3 = 9 

여기까지 살펴보았을 때, dp[3]은 3도, -1도 아닌 9이다.

왜냐하면, arr[2]까지의 최대값이 6으로 '양수'인데, 당연히 양수 + 양수 = 더 큰 양수 이므로 dp[2] + arr[3] = dp[3]이 가질 수 있는 더 최대 양수 값이 된다.

 

이를 통해, 아래와 같은 점화식을 얻을 수 있다. (0은 값에 영향을 미치지 않으므로 포함시킨다.)

dp[i-1] >= 0 일때, dp[i] = dp[i-1] + arr[i] 

 

이어서,

dp[4] = dp[3] + arr[4]  = 9 + 1 = 10 (dp[3] > 0)

dp[5] = dp[4] + arr[5]  = 10 5 = 15 (dp[4] > 0)

dp[6] = dp[5] + arr[6] = 15 + 6 = 21 (dp[5] > 0)

 

dp[7] = dp[6] + arr[7] = 21 + (-35) = -14 (dp[6] > 0)

dp[8] = dp[7] + arr[8] = -14 + 12 = -2  ← ????

 

여기서 위의 점화식을 만족 시킬 수 없는 예외의 경우가 발생한다!

dp[7]은 arr[7]을 끝값으로 가지는 연속된 최대 합의 값인데 dp[7] + arr[8]이 arr[8]을 단독으로 갖는 경우보다 더 작은 값을 갖게된다. 

 

=> dp[7] + arr[8] < arr[8]

=> dp[7] < 0

 

위의 수식과 같이, dp[7]이 음수의 값을 가지므로 음수 + 양수 = 작아진 양수.. 가 되므로 dp[i-1]이 음수일 경우 아예 더하지 않고, arr[i] 값만을 단독으로 갖는 것이 최대값을 가질 수 있다.

 

이를통해, 아래와 같은 두번째 점화식을 얻을 수 있다.

dp[i-1] < 0 일때, dp[i] = arr[i] 

따라서 dp[i-1]값이 양수인지, 음수인지에 따라 if문을 적절히 작성하면 문제를 쉽게 풀이할 수 있다.


소스코드

 

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int compare(int n1, int n2) {
    return n1 > n2 ? n1 : n2;
}
int main() {
    int num;
    int result = 0;
    int arr[100001] = { 0, };
    int dp[100001] = { 0, };
 
    scanf("%d", &num);
    for (int i = 1; i <= num; i++) {
        scanf("%d", &arr[i]);
    }
 
    dp[1] = arr[1];
    result = dp[1];
    for (int i = 2; i <= num; i++) {
        if (dp[i - 1] > 0)
            dp[i] = dp[i - 1] + arr[i];
        else if (dp[i - 1] < 0)
            dp[i] = arr[i];
        result = compare(dp[i], result);
    }
    printf("%d", result);
}
Colored by Color Scripter
cs

'알고리즘' 카테고리의 다른 글

카운팅정렬, 계수정렬 알고리즘(Counting sort) + 백준 10989번  (4) 2022.11.07
[백준 11052] 카드 구매하기 (DP, 점화식)  (4) 2022.10.29
[백준 2579] 계단 오르기 (DP, 점화식)  (2) 2022.10.18
[백준 10844, 11057] 쉬운 계단 수, 오르막 수 (DP, 점화식)  (2) 2022.10.12
[백준 11726, 11727] 2XN 타일링 (DP, 점화식)  (3) 2022.10.11
'알고리즘' 카테고리의 다른 글
  • 카운팅정렬, 계수정렬 알고리즘(Counting sort) + 백준 10989번
  • [백준 11052] 카드 구매하기 (DP, 점화식)
  • [백준 2579] 계단 오르기 (DP, 점화식)
  • [백준 10844, 11057] 쉬운 계단 수, 오르막 수 (DP, 점화식)
공부하는 나무꾼
공부하는 나무꾼
  • 공부하는 나무꾼
    헤맨 만큼 내 땅이다
    공부하는 나무꾼
  • 전체
    오늘
    어제
  • 글쓰기/관리
    • 분류 전체보기
      • AWS
      • SAA-C03
      • 네트워크 보안
      • 최신정보보안이론
      • 컴퓨터네트워크
      • OpenFaaS
      • C++
      • Java
      • HTML, CSS
      • 자료구조
      • 알고리즘
      • 정보보안인재양성
      • [MAC]트러블슈팅&Tip
      • 공부
      • Web(Django)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    웹서버
    aws-c03
    java #자바 #객체지향프로그래밍 #복습
    SAA-C03
    Web Server
    자격증
    web application server
    웹클라이언트
    웹애플리케이션서버
    등록번호
    cloud
    클라우드
    WAS
    AWS
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
공부하는 나무꾼
[백준 1912] 연속 합 (DP, 점화식)
상단으로

티스토리툴바