-
[Dev-Ping9] 백준 13398번 : 연속합 2 (Java)코딩테스트/백준 2021. 11. 8. 21:03
# Description
# 어떤 접근 방법이 좋을까?
1. 문제의 답은 최적의 해를 구하는 것
2. 이전의 해를 이용하여, 지금의 해를 구할 수 있는가?
(부분 구조가 성립하는가? => Yes)
=> 1번과 2번 문항을 통해 DP를 적용 시킬 수 있다는 근거를 가지게 되었다.
3. 단순무식하게 풀었을 때 연산량이 많은가?
f(a) 를 a 부터 시작한 [연속합2] 의 최대라 정의 했을때,
=> 1~N , 2~N , 3~N, .... , N~N
=> O(N^2)
4. 공간의 제약이 많은가, 시간의 제약이 많은가
=> Description을 보면, 확실히 시간의 제약이 많다. (시간제한 및 n의 최대값)
=> 보통 1초에 1억번 연산가능 (N^2 이면, N=100_000일때, 1천억번 연산해야함 => 1천초 소요..)
# DP 배열 정의하기
- 가장 중요한 부분이라 생각한다.
- 수학식이 아닌 한글과 같은 인간의 언어로 정의가 가능해야 무얼할지 확신이 서기 때문이다.
접근 방법을 DP로 결정하게 된 이유는, 문제에서 정의 된 이전의 해(정답)로 지금의 해를 구할 수 있다는 것 이었다.
그럼 최대한 해당 논리에서 벗어나지 않게 배열을 정의해야 한다.
문제의 해를 [연속합2]로 정의 하겠다.
문제에서 [연속합2]의 정의는 1개의 숫자를 제거하거나, 제거를 하지않았을 때의 부분수열의 최대 연속합이다.
즉, 우리가 사용할 DP 방식으로 풀어낼 때, Memoization 으로 사용할 배열의 정의는 아래와 같다.
연속합2(n) = n까지의 부분수열의 최대합 중 [ 1개의 숫자를 제거한 값 & 제거하지 않았을때의 값 ] 의 최댓값
# DP 배열 점화식(규칙) 찾기
위의 정의에 따라, 우리는 원하는 해를 구하기 위해, 두개의 저장된 값이 필요하다는 것을 알 수 있다.
[1] 1개의 숫자를 제거한 값
[2] 숫자를 제거하지 않았을때의 값
* expeceted solution : [1] 과 [2] 중 최댓값
[1] 은 [2] 의 값을 토대로 만들어 진다. 그러므로, [2]를 먼저 정의한다.
[2] noDeleted[n] : n을 pick 했을때, n까지의 최대 연속수열의 합
- 연속적인 수열이어야 하므로, 이전의 해인 n-1 등과의 관계를 맺기 위해선 n을 pick 했다고 정의를 내려야 dp1[n-1] 을 가져왔을때도 n-1 이 pick 되어있는 상태가 되기 때문이다.
- noDeleted[n] = max(arr[n], noDeleted[n-1]+arr[n])
[1] oneDeleted[n] : n까지의 연속합 중, 1개의 숫자를 제거 했을때의 최대값
- oneDeleted[n] = max( n번째 숫자를 제거함, n번째 숫자를 제거하지 않음 )
- oneDeleted[n] = max( noDeleted[n-1], oneDeleted[n-1]+arr[n] )
# 구현코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class Main{ static int[] arr; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); arr = new int[n]; StringTokenizer st = new StringTokenizer(br.readLine(), " "); for(int i=0; i<n; i++){ arr[i] = Integer.parseInt(st.nextToken()); } /* noDeleted[n] : n pick 시 , n 까지의 최대 연속합 oneDeleted[n] : 숫자 하나를 지웠을 때, n까지의 최대 연속합 : [case1] drop arr[n] => noDeleted[n-1] : [case2] pick arr[n] => oneDeleted[n-1]+arr[n] */ long noDeleted[] = new long[n]; long oneDeleted[] = new long[n]; noDeleted[0]= arr[0]; oneDeleted[0]= arr[0]; long result = arr[0]; for(int i=1; i<n; i++){ noDeleted[i] = Math.max(arr[i], noDeleted[i-1]+arr[i]); oneDeleted[i]= Math.max(noDeleted[i-1],oneDeleted[i-1]+arr[i]); result = Math.max(result, Math.max(noDeleted[i],oneDeleted[i])); } System.out.println(result); } } /* 15 100 -2000 -4 -1 3 1 5 6 -10 -2 -4 -1000 12 21 -1 */
# 실행화면
728x90'코딩테스트 > 백준' 카테고리의 다른 글
[Dev-Ping9] 백준 1011번 - Fly me to the Alpha Centauri (Java) (0) 2021.11.17 [Dev-Ping9] 백준 10757번 - 큰 수 A+B (Java) (0) 2021.11.16 [Dev-Ping9] 백준 2775번 - 부녀회장이 될테야 (Java) (0) 2021.11.16 [Dev-Ping9] 백준 2869번 - 달팽이는 올라가고 싶다 (Java) (0) 2021.11.16 [Dev-Ping9] 백준 1193번 - 분수찾기 (Java) (0) 2021.11.16