알고리즘 기초1 Java

다이나믹 프로그래밍_1912 : 연속합 JAVA

람대리 2024. 5. 2. 20:32
728x90

문제

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

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

입력

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

출력

첫째 줄에 답을 출력한다.

예제 입력 1 복사

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

예제 출력 1 복사

33

예제 입력 2 복사

10
2 1 -4 3 4 -4 6 5 -5 1

예제 출력 2 복사

14

예제 입력 3 복사

5
-1 -2 -3 -4 -5

예제 출력 3 복사

-1

 

첫번째 예시는 다음과 같습니다.

두번째 예시는 다음과 같습니다.

두번째 예시를 보면 중간에 index 5가 음수이지만, index 7까지 합한 것이 최대값임을 알 수 있습니다. 즉 음수와 상관없이 연속적으로 선택한 수의 합 최대값을 찾으면 됩니다.

 

예시와 dp값을 비교하면 다음과 같습니다

 

예시 1

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

dp :  10 6 9 10 15 21 -14 12 33 32

 

예시 2

arr : 2 1 -4 3 4 -4 6 5 -5 1

dp :  2 3 -1 3 7 3 9 14 9 10

 

dp를 구하기 위한 점화식은 다음과 같습니다.

dp[i] = Math.max(dp[i-1]+arr[i],arr[i]); // 그동안 더한값에 현재 값을 더한 값과 현재 값을 비교하여 큰 값이 dp[i]에 들어갑니다

 

점화식을 바탕으로 구현한 방식은 다음과 같습니다.

StringBuilder와 Buttom-up 방식을 이용하였습니다.

 

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

class Main{
	public static void main(String[] args){
    	StringBuilder sb = new StringBuilder(new InputStreamReader(System.in));
        int N = Integer.parseInt(sb.readLine());
        
        int[] arr = new int[N];
        int[] dp = new int[N];
        
        StringTokenizer st = new StringTokenzier(br.readLine()," ");
        
        for(int i=0;i<N;i++){
        	arr[i] = Integer.parseInt(st.nextToken());
        }
        
        dp[0] = arr[0];
        int max = dp[o];
        
        for(int i=1;i<N;i++){
        	dp[i] = Math.max(dp[i-1]+arr[i],arr[i]);
            max = Math.max(max,dp[i]);
        }
        System.out.print(max);
    }
}