λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Algorithm

[λ°±μ€€] 1932번: μ •μˆ˜ μ‚Όκ°ν˜•(DP, λ™μ κ³„νšλ²•)

by 주발2 2020. 2. 20.
λ°˜μ‘ν˜•

λ°±μ€€ 1932번 - μ •μˆ˜ μ‚Όκ°ν˜•(DP)

 

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

 

1932번: μ •μˆ˜ μ‚Όκ°ν˜•

문제 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 μœ„ 그림은 크기가 5인 μ •μˆ˜ μ‚Όκ°ν˜•μ˜ ν•œ λͺ¨μŠ΅μ΄λ‹€. 맨 μœ„μΈ΅ 7λΆ€ν„° μ‹œμž‘ν•΄μ„œ μ•„λž˜μ— μžˆλŠ” 수 쀑 ν•˜λ‚˜λ₯Ό μ„ νƒν•˜μ—¬ μ•„λž˜μΈ΅μœΌλ‘œ λ‚΄λ €μ˜¬ λ•Œ, μ΄μ œκΉŒμ§€ μ„ νƒλœ 수의 합이 μ΅œλŒ€κ°€ λ˜λŠ” 경둜λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λΌ. μ•„λž˜μΈ΅μ— μžˆλŠ” μˆ˜λŠ” ν˜„μž¬ μΈ΅μ—μ„œ μ„ νƒλœ 수의 λŒ€κ°μ„  μ™Όμͺ½ λ˜λŠ” λŒ€κ°μ„  였λ₯Έμͺ½μ— μžˆλŠ” 것 μ€‘μ—μ„œλ§Œ 선택할 수 μžˆλ‹€. μ‚Όκ°ν˜•μ˜ ν¬κΈ°λŠ” 1 이상 500 μ΄ν•˜μ΄λ‹€. μ‚Όκ°ν˜•μ„ 이루고 μžˆλŠ” 각 μˆ˜λŠ”

www.acmicpc.net

μ½”λ“œ

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Main {

	// n측에 μžˆλŠ” κ²½λ‘œμ€‘ μ΅œλŒ“κ°’ μ°ΎκΈ°
	public static int findMax(int n, int[][] arr) {
		int max = 0;
		for(int i=0; i<n; i++) 
			if(arr[n-1][i] > max)
				max = arr[n-1][i];
		return max;
	}

	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		Scanner scan = new Scanner(System.in);

		int n = Integer.parseInt(bf.readLine());
		int[][] dp = new int[n][n];
		StringTokenizer st;

		// μΈ΅λ³„λ‘œ μ •μˆ˜ μž…λ ₯λ°›κΈ°
		for(int i=0; i<n; i++) { 
			st = new StringTokenizer(bf.readLine());
			for(int j=0; j<=i; j++) {
				dp[i][j] = Integer.parseInt(st.nextToken());
			}
		}

		for(int i=1; i<n; i++) {
			for(int j=0; j<=i; j++) {
				// μΈ΅λ³„λ‘œ μ € μ™Όμͺ½μΌ λ•Œ
				//  -> λ°”λ‘œ μœ—μΈ΅(dp[i-1][j]) κ³Ό κ·Έ μΈ΅(dp[i][j])의 ν•© 1가지밖에 μ—†μŒ.
				if(j == 0)
					dp[i][j] = dp[i-1][j] + dp[i][j];

				// μΈ΅λ³„λ‘œ μ € 였λ₯Έμͺ½μΌ λ•Œ
				//  -> λ°”λ‘œ μœ—μΈ΅(dp[i-1][j-1]) κ³Ό κ·Έ μΈ΅(dp[i][j])의 ν•© 1가지밖에 μ—†μŒ.
				else if(j == i)
					dp[i][j] = dp[i-1][j-1] + dp[i][j];
				
				// μΈ΅λ³„λ‘œ 맨왼μͺ½, 맨였λ₯Έμͺ½μ΄ μ•„λ‹Œ μ€‘κ°„μΌλ•Œ
				//  -> λŒ€κ°μ„  μ™Όμͺ½μœ„ / λŒ€κ°μ„  였λ₯Έμͺ½μœ„μ™€μ˜ ν•© 쀑 큰 κ°’ 
				else 
					dp[i][j] = Math.max(dp[i-1][j-1] + dp[i][j], dp[i-1][j] + dp[i][j]);
			}
		}

		System.out.println(findMax(n, dp));
		bf.close();
	}

}

풀이

λ¬Έμ œμ—μ„œ λ‚˜μ˜¨ 5측을 κΈ°μ€€μœΌλ‘œ 보자.

 * 첫 측은 λ°°μ—΄μ˜ 인덱슀 μ‹œμž‘μ— 따라 0측으둜 ν•΄μ„œ 0, 1, 2, 3, 4측으둜 νŒλ‹¨ν•¨.

κ°€μž₯ μ™Όμͺ½μ˜ κ°’(7, 3, 8, 2, 4)λŠ” 선택할 수 μžˆλŠ” κ²½μš°κ°€ 1가지 밖에 μ—†λ‹€.(μ•„λž˜μ‚¬μ§„)

λ”°λΌμ„œ μΈ΅λ§ˆλ‹€ jκ°€ 0μΌλ•ŒλŠ” λ°”λ‘œ μœ—μΈ΅κ°’ + ν˜„μž¬μΈ΅κ°’μ„ 더해쀀닀.

1μΈ΅ -> 7 + 3

2μΈ΅ -> 7 + 3 + 8

3μΈ΅ -> 7 + 3 + 8 + 2

4μΈ΅ -> 7 + 3 + 8 + 2 + 4

if(j == 0)
    dp[i][j] = dp[i-1][j] + dp[i][j];

 

μΈ΅λ§ˆλ‹€ jκ°€ iμΌλ•Œ(κ°€μž₯ 였λ₯Έμͺ½κ°’)도 λ§ˆμ°¬κ°€μ§€λ‘œ 선택할 수 μžˆλŠ” κ²½μš°κ°€ 1가지 밖에 μ—†λ‹€.

λ”°λΌμ„œ μΈ΅λ§ˆλ‹€ jκ°€ iμΌλ•ŒλŠ” λŒ€κ°μ„ μ™Όμͺ½μœ„에 κ°’ + ν˜„μž¬μΈ΅ 값을 더해쀀닀.

1μΈ΅ -> 7 + 8

2μΈ΅ -> 7 + 8 + 0

3μΈ΅ -> 7 + 8 + 0 + 4

4μΈ΅ -> 7 + 8 + 0 + 4 + 5

else if(j == i)
    dp[i][j] = dp[i-1][j-1] + dp[i][j];

 

λ§ˆμ§€λ§‰μœΌλ‘œ jκ°€ κ°€μž₯ μ™Όμͺ½λ„ μ•„λ‹ˆκ³  κ°€μž₯ 였λ₯Έμͺ½λ„ μ•„λ‹Œ μ€‘κ°„κ°’λ“€μΌλ•Œ

μ™Όμͺ½ λŒ€κ°μ„ μœ„μ™€ 였λ₯Έμͺ½ λŒ€κ°μ„ μœ„μ™€μ˜ ν•© 쀑 큰값을 ꡬ해주면 λœλ‹€.

else 
    dp[i][j] = Math.max(dp[i-1][j-1] + dp[i][j], dp[i-1][j] + dp[i][j]);

 

μœ„ 반볡문이 nμΈ΅κΉŒμ§€ λλ‚˜λ©΄,

n측의 각 값듀은 ν•΄λ‹Ή 측으둜 μ‘΄μž¬ν•˜λŠ” κ°’ 쀑 μ΅œλŒ“κ°’μ΄ λœλ‹€.

(4,3) 의 6μ΄λΌλŠ” κ°’ κΉŒμ§€ λ”ν•˜λ €λ©΄

(3,2) OR (3,3)의 κ°’ κΉŒμ§€ λ”ν•œ 것쀑 큰 κ°’κ³Ό 합을 ꡬ해야 ν•œλ‹€.

 

5측을 κΈ°μ€€μœΌλ‘œ 각 과정을 μ‚΄νŽ΄λ³΄λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

 

λ°˜μ‘ν˜•

λŒ“κΈ€