코딩테스트/BOJ

[BOJ] 13398 연속합2 - JAVA

5월._. 2022. 12. 16.
728x90

1. 문제

 

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가 된다.


2. 풀이

dp를 이용했다. 

dp[i]는 i번째 수를 포함한 최대 연속합이다.

dp[i][0]은 수를 제거하지 않은 최대 연속합이다. 따라서 [i-1][0]이 음수가 아닐때만 더하고, 음수일때는 i번째 수만 저장한다.

dp[i][1]은 수를 하나 제거한 최대 연속합이다. 이 경우는 두 가지가 있는데

    1) [i-2][0]에 현재 수를 더한(i-1를 제거) 경우

    2) [i-1][1]에 현재 수를 더한 경우

이다. 

그림으로 예시를 들면 이런 식이다.

import java.io.*;
import java.util.*;

public class BOJ_13398_연속합2 {
   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      int N = Integer.parseInt(in.readLine());
      StringTokenizer st = new StringTokenizer(in.readLine());
      int[][] dp = new int[N+1][2];
      int max = dp[1][0] = dp[1][1] = Integer.parseInt(st.nextToken());
      for(int i=2;i<=N;i++){
         int num = Integer.parseInt(st.nextToken());
         dp[i][0] = Math.max(0, dp[i-1][0])+num;
         dp[i][1] = Math.max(dp[i-2][0], dp[i-1][1])+num;
         max = Math.max(max, Math.max(dp[i][0],dp[i][1]));
      }
      System.out.println(max);
   }
}

3. 결과

dp문제는 항상 생각한 거에 비해 코드가 단출하다.

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 1068 트리 - JAVA  (0) 2023.02.08
[BOJ] 1963 소수경로 - JAVA  (0) 2022.12.17
[BOJ] 1922 네트워크 연결 - JAVA  (0) 2022.12.16
[BOJ] 18111 마인크래프트 - JAVA  (0) 2022.12.16
[BOJ] 2004 조합 0의 개수 - JAVA  (0) 2022.07.29

댓글