728x90
1. 문제
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 |
댓글