[πŸ“šμ΄μ½”ν…Œ #5] λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° πŸ”₯

졜호빈·2023λ…„ 5μ›” 5일
0
post-thumbnail

좜처 : https://www.youtube.com/watch?v=5Lu34WIx2Us&list=PLRx0vPvlEmdAghTr5mXQxGpHjWqSz0dgC&index=6


πŸ“Œ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°


  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ€ λ©”λͺ¨λ¦¬λ₯Ό 적절히 μ‚¬μš©ν•˜μ—¬ μˆ˜ν–‰ μ‹œκ°„ νš¨μœ¨μ„±μ„ λΉ„μ•½μ μœΌλ‘œ ν–₯μƒμ‹œν‚€λŠ” 방법
  • 이미 κ³„μ‚°λœ κ²°κ³Ό(μž‘μ€ 문제)λŠ” λ³„λ„μ˜ λ©”λͺ¨λ¦¬ μ˜μ—­μ— μ €μž₯ν•˜μ—¬ λ‹€μ‹œ κ³„μ‚°ν•˜μ§€ μ•Šλ„λ‘ 함
  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ˜ κ΅¬ν˜„μ€ 일반적으둜 두 가지 방식
    νƒ‘λ‹€μš΄(μœ„ ➑️ μ•„λž˜)κ³Ό 보텀업(μ•„λž˜ ➑️ μœ„)으둜 κ΅¬μ„±λœλ‹€.
  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ€ λ™μ κ³„νšλ²•μ΄λΌκ³ λ„ λΆˆλ¦°λ‹€.

νƒ‘λ‹€μš΄ VS 보텀업

  • νƒ‘λ‹€μš΄(λ©”λͺ¨μ΄μ œμ΄μ…˜) 방식은 ν•˜ν–₯식이라고도 ν•˜λ©° 보텀업 방식은 상ν–₯식이라고도 ν•œλ‹€.
  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ˜ μ „ν˜•μ μΈ ν˜•νƒœλŠ” 보텀업 방식
  • κ²°κ³Ό μ €μž₯용 λ¦¬μŠ€νŠΈλŠ” DP ν…Œμ΄λΈ”μ΄λΌκ³  λΆ€λ₯Έλ‹€.

πŸ€” λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ˜ 쑰건

1. 졜적 λΆ€λΆ„ ꡬ쑰 (Optimal Substructure)
πŸ‘‰πŸ» 큰 문제λ₯Ό μž‘μ€ 문제둜 λ‚˜λˆŒ 수 있으며 μž‘μ€ 문제의 닡을 λͺ¨μ•„μ„œ 큰 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλ‹€.

2. μ€‘λ³΅λ˜λŠ” λΆ€λΆ„ 문제 (Overlapping Subproblem)
πŸ‘‰πŸ» λ™μΌν•œ μž‘μ€ 문제λ₯Ό 반볡적으둜 ν•΄κ²°ν•΄μ•Ό ν•œλ‹€.



πŸ€“ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ ν™œμš©ν•˜μ—¬ ν•΄κ²°ν•  수 μžˆλŠ” 문제 : ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄


ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ 점화식(μΈμ ‘ν•œ ν•­λ“€ μ‚¬μ΄μ˜ 관계식)으둜 ν‘œν˜„ν•˜λ©΄ μ•„λž˜κ³Ό κ°™λ‹€.

πŸ‘‰πŸ» ν”„λ‘œκ·Έλž˜λ°μ—μ„œλŠ” μ΄λŸ¬ν•œ μˆ˜μ—΄μ„ λ°°μ—΄μ΄λ‚˜ 리슀트λ₯Ό μ΄μš©ν•΄ ν‘œν˜„


ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ΄ κ³„μ‚°λ˜λŠ” 과정은 μ•„λž˜μ™€ 같이 ν‘œν˜„ν•  수 μžˆλ‹€.


🀯 μ‹œκ°„ λ³΅μž‘λ„ 뢄석

βœ… λ‹¨μˆœ μž¬κ·€ ν•¨μˆ˜λ‘œ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ ν•΄κ²°ν•˜λ©΄ μ§€μˆ˜ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§€κ²Œ λœλ‹€.
βœ… n이 쑰금만 컀져도 κΈ°ν•˜κΈ‰μˆ˜μ μœΌλ‘œ λ§Žμ€ μ‹œκ°„μ΄ ν•„μš”ν•¨
βœ… λ‹€μŒκ³Ό 같이 f(2)κ°€ μ—¬λŸ¬ 번 ν˜ΈμΆœλ˜λŠ” 것을 확인할 수 μžˆλ‹€. (μ€‘λ³΅λ˜λŠ” λΆ€λΆ„ 문제)

βœ… ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” μ•„λž˜μ™€ κ°™λ‹€.

λΉ…μ˜€ ν‘œκΈ°λ²•μ„ κΈ°μ€€μœΌλ‘œ f(30)을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄ μ•½ 10μ–΅κ°€λŸ‰μ˜ 연산을 μˆ˜ν–‰ν•΄μ•Ό ν•œλ‹€. κ·Έλ ‡λ‹€λ©΄ f(100)을 κ³„μ‚°ν•˜κΈ° μœ„ν•΄ μ–Όλ§ˆλ‚˜ λ§Žμ€ 연산을 μˆ˜ν–‰ν•΄μ•Ό ν• κΉŒ ❓
πŸ‘‰πŸ» f(30)κ³ΌλŠ” 비ꡐ도 μ•ˆλ˜κ²Œ λ§Žμ€ 연산을 ν•΄μ•Όν•  것이닀.



λ¨Όμ €, ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ΄ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ˜ μ‚¬μš© 쑰건을 λ§Œμ‘±ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€.

1. `졜적 λΆ€λΆ„ ꡬ쑰` : 큰 문제λ₯Ό μž‘μ€ 문제둜 λ‚˜λˆŒ 수 μžˆμŠ΅λ‹ˆλ‹€.
2. `μ€‘λ³΅λ˜λŠ” λΆ€λΆ„ 문제` : λ™μΌν•œ μž‘μ€ 문제λ₯Ό 반볡적으둜 ν•΄κ²°ν•©λ‹ˆλ‹€.

πŸ‘‰πŸ» ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ€ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ˜ μ‚¬μš© 쑰건을 λ§Œμ‘±ν•©λ‹ˆλ‹€.



✏️ [νƒ‘λ‹€μš΄] λ©”λͺ¨μ΄μ œμ΄μ…˜ (Memoization)

  • λ©”λͺ¨μ΄μ œμ΄μ…˜μ€ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ κ΅¬ν˜„ν•˜λŠ” 방법 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.
  • ν•œ 번 κ³„μ‚°ν•œ κ²°κ³Όλ₯Ό λ©”λͺ¨λ¦¬ 곡간에 λ©”λͺ¨ν•˜λŠ” κΈ°λ²•μž…λ‹ˆλ‹€.
  • 같은 문제λ₯Ό λ‹€μ‹œ ν˜ΈμΆœν•˜λ©΄ λ©”λͺ¨ν–ˆλ˜ κ²°κ³Όλ₯Ό κ·ΈλŒ€λ‘œ κ°€μ Έμ˜΅λ‹ˆλ‹€.
  • 값을 기둝해 λ†“λŠ”λ‹€λŠ” μ μ—μ„œ 캐싱(Caching)이라고도 ν•©λ‹ˆλ‹€.

μ—„λ°€νžˆ λ§ν•˜λ©΄ λ©”λͺ¨μ΄μ œμ΄μ…˜μ€ μ˜μ „μ— κ³„μ‚°λœ κ²°κ³Όλ₯Ό μΌμ‹œμ μœΌλ‘œ 기둝해 λ†“λŠ” 넓은 κ°œλ…μ„ μ˜λ―Έν•œλ‹€. λ”°λΌμ„œ λ©”λͺ¨μ΄μ œμ΄μ…˜μ€ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ— κ΅­ν•œλœ κ°œλ…μ€ μ•„λ‹ˆλ‹€. ν•œ 번 κ³„μ‚°λœ κ²°κ³Όλ₯Ό λ‹΄μ•„ λ†“κΈ°λ§Œ ν•˜κ³  λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μœ„ν•΄ ν™œμš©ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€.
πŸ‘‰πŸ» λ”°λΌμ„œ λ©”λͺ¨μ΄μ œμ΄μ…˜κ³Ό λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ€ 같은 κ°œλ…μ΄ μ•„λ‹ˆλ‹€!

[νƒ‘λ‹€μš΄] λ©”λͺ¨μ΄μ œμ΄μ…˜ (Memoization) μ†ŒμŠ€μ½”λ“œ

python

# ν•œ 번 κ³„μ‚°λœ κ²°κ³Όλ₯Ό λ©”λͺ¨μ΄μ œμ΄μ…˜(Memoization)ν•˜κΈ° μœ„ν•œ 리슀트 μ΄ˆκΈ°ν™”
d = [0] * 100

# ν”Όλ³΄λ‚˜μΉ˜ ν•¨μˆ˜(Fibonacci Function)λ₯Ό μž¬κ·€ν•¨μˆ˜λ‘œ κ΅¬ν˜„ (νƒ‘λ‹€μš΄ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°)
def fibo(x):
    # μ’…λ£Œ 쑰건(1 ν˜Ήμ€ 2일 λ•Œ 1을 λ°˜ν™˜)
    if x == 1 or x == 2:
        return 1
    # 이미 κ³„μ‚°ν•œ 적 μžˆλŠ” 문제라면 κ·ΈλŒ€λ‘œ λ°˜ν™˜
    if d[x] != 0:
        return d[x]
    # 아직 κ³„μ‚°ν•˜μ§€ μ•Šμ€ 문제라면 점화식에 λ”°λΌμ„œ ν”Όλ³΄λ‚˜μΉ˜ κ²°κ³Ό λ°˜ν™˜
    d[x] = fibo(x - 1) + fibo(x - 2)
    return d[x]

print(fibo(99))

Java

import java.util.*;

public class Main {

    // ν•œ 번 κ³„μ‚°λœ κ²°κ³Όλ₯Ό λ©”λͺ¨μ΄μ œμ΄μ…˜(Memoization)ν•˜κΈ° μœ„ν•œ λ°°μ—΄ μ΄ˆκΈ°ν™”
    public static long[] d = new long[100];

    // ν”Όλ³΄λ‚˜μΉ˜ ν•¨μˆ˜(Fibonacci Function)λ₯Ό μž¬κ·€ν•¨μˆ˜λ‘œ κ΅¬ν˜„ (νƒ‘λ‹€μš΄ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°)
    public static long fibo(int x) {
        // μ’…λ£Œ 쑰건(1 ν˜Ήμ€ 2일 λ•Œ 1을 λ°˜ν™˜)
        if (x == 1 || x == 2) {
            return 1;
        }
        // 이미 κ³„μ‚°ν•œ 적 μžˆλŠ” 문제라면 κ·ΈλŒ€λ‘œ λ°˜ν™˜
        if (d[x] != 0) {
            return d[x];
        }
        // 아직 κ³„μ‚°ν•˜μ§€ μ•Šμ€ 문제라면 점화식에 λ”°λΌμ„œ ν”Όλ³΄λ‚˜μΉ˜ κ²°κ³Ό λ°˜ν™˜
        d[x] = fibo(x - 1) + fibo(x - 2);
        return d[x];
    }

    public static void main(String[] args) {
        System.out.println(fibo(50));
    }
}

🀯 μ‹œκ°„ λ³΅μž‘λ„ 뢄석

λ©”λͺ¨μ΄μ œμ΄μ…˜μ„ μ΄μš©ν•˜λŠ” 경우 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄ ν•¨μˆ˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” 0(N)이닀.



[보텀업] λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° μ†ŒμŠ€μ½”λ“œ

python

# μ•žμ„œ κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
d = [0] * 100

# 첫 번째 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ™€ 두 번째 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜λŠ” 1
d[1] = 1
d[2] = 1
n = 99

# ν”Όλ³΄λ‚˜μΉ˜ ν•¨μˆ˜(Fibonacci Function) 반볡문으둜 κ΅¬ν˜„(보텀업 λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°)
for i in range(3, n + 1):
    d[i] = d[i - 1] + d[i - 2]

print(d[n])

Java

import java.util.*;

public class Main {

    public static long[] d = new long[100];

    public static void main(String[] args) {
        // 첫 번째 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ™€ 두 번째 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜λŠ” 1
        d[1] = 1;
        d[2] = 1;
        int n = 50; // 50번째 ν”Όλ³΄λ‚˜μΉ˜ 수λ₯Ό 계산

        // ν”Όλ³΄λ‚˜μΉ˜ ν•¨μˆ˜(Fibonacci Function) 반볡문으둜 κ΅¬ν˜„(보텀업 λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°)
        for (int i = 3; i <= n; i++) {
            d[i] = d[i - 1] + d[i - 2];
        }
        System.out.println(d[n]);
    }
}



πŸ€— λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° vs λΆ„ν•  정볡

  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°κ³Ό λΆ„ν•  정볡은 λͺ¨λ‘ 졜적 λΆ€λΆ„ ꡬ쑰λ₯Ό κ°€μ§ˆ λ•Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    졜적 λΆ€λΆ„ ꡬ쑰 : 큰 문제λ₯Ό μž‘μ€ 문제둜 λ‚˜λˆŒ 수 있으며 μž‘μ€ 문제의 닡을 λͺ¨μ•„μ„œ 큰 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλŠ” 상황
  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°κ³Ό λΆ„ν•  μ •λ³΅μ˜ 차이점은 λΆ€λΆ„ 문제의 쀑볡 μž…λ‹ˆλ‹€.
    βœ… λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° λ¬Έμ œμ—μ„œλŠ” 각 λΆ€λΆ„ λ¬Έμ œλ“€μ΄ μ„œλ‘œ 영ν–₯을 미치며 λΆ€λΆ„ λ¬Έμ œκ°€ μ€‘λ³΅λ©λ‹ˆλ‹€.
    βœ… λΆ„ν•  정볡 λ¬Έμ œμ—μ„œλŠ” λ™μΌν•œ λΆ€λΆ„ λ¬Έμ œκ°€ 반볡적으둜 κ³„μ‚°λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.


λΆ„ν•  μ •λ³΅μ˜ λŒ€ν‘œμ μΈ μ˜ˆμ‹œμΈ 퀡 정렬을 μ‚΄νŽ΄λ³΄μž

  • ν•œ 번 κΈ°μ€€ μ›μ†Œ(Pivot)κ°€ 자리λ₯Ό λ³€κ²½ν•΄μ„œ 자리λ₯Ό 작으면 κ·Έ κΈ°μ€€ μ›μ†Œμ˜ μœ„μΉ˜λŠ” λ°”λ€Œμ§€ μ•ŠλŠ”λ‹€.
  • λΆ„ν•  이후에 ν•΄λ‹Ή 피벗을 λ‹€μ‹œ μ²˜λ¦¬ν•˜λŠ” λΆ€λΆ„ λ¬Έμ œλŠ” ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€.



✏️ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° λ¬Έμ œμ— μ ‘κ·Όν•˜λŠ” 방법

  • 주어진 λ¬Έμ œκ°€ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° μœ ν˜•μž„μ„ νŒŒμ•…ν•˜λŠ” 것이 μ€‘μš”
  • κ°€μž₯ λ¨Όμ € 그리디, κ΅¬ν˜„, μ™„μ „ 탐색 λ“±μ˜ μ•„μ΄λ””μ–΄λ‘œ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλŠ”μ§€ 검토해보고 풀이 방법이 λ– μ˜€λ₯΄μ§€ μ•ŠμœΌλ©΄ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ κ³ λ €ν•΄ 보자
  • 일단 μž¬κ·€ ν•¨μˆ˜λ‘œ λΉ„νš¨μœ¨μ μΈ μ™„μ „ 탐색 ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•œ 뒀에 (νƒ‘λ‹€μš΄) μž‘μ€ λ¬Έμ œμ—μ„œ κ΅¬ν•œ 닡이 큰 λ¬Έμ œμ—μ„œ κ·ΈλŒ€λ‘œ μ‚¬μš©λ  수 있으면, μ½”λ“œλ₯Ό κ°œμ„ ν•˜λŠ” 방법을 μ‚¬μš©ν•  수 μžˆλ‹€.
  • 일반적인 μ½”λ”© ν…ŒμŠ€νŠΈ μˆ˜μ€€μ—μ„œλŠ” κΈ°λ³Έ μœ ν˜•μ˜ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° λ¬Έμ œκ°€ μΆœμ œλ˜λŠ” κ²½μš°κ°€ λ§Žλ‹€.




βœ”οΈ [μ‹€μŠ΅] κ°œλ―Έμ „μ‚¬ 🐜 : 졜적 λΆ€λΆ„ ꡬ쑰, 보텀업


a, = 1번째 μ‹λŸ‰μ°½κ³ κΉŒμ§€μ˜ 졜적의 ν•΄ (얻을 수 μžˆλŠ” μ‹λŸ‰μ˜ μ΅œλŒ“κ°’)이라고 μ •μ˜ν•œλ‹€λ©΄ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μ μš©ν•  수 μžˆλ‹€.


μ™Όμͺ½λΆ€ν„° μ°¨λ‘€λŒ€λ‘œ μ‹λŸ‰μ°½κ³ λ₯Ό ν„΄λ‹€κ³  ν–ˆμ„ λ•Œ, νŠΉμ •ν•œ 번째의 μ‹λŸ‰μ°½κ³ μ— λŒ€ν•΄μ„œ 털지 μ•ˆ ν„Έμ§€μ˜ μ—¬λΆ€λ₯Ό κ²°μ •ν•˜λ©΄, μ•„λž˜ 2가지 경우 μ€‘μ—μ„œ 더 λ§Žμ€ μ‹λŸ‰μ„ ν„Έ 수 μžˆλŠ” 경우λ₯Ό μ„ νƒν•˜λ©΄ λœλ‹€.


이λ₯Ό μˆ˜μ‹μœΌλ‘œ ν‘œν˜„ν•˜λ©΄


점화식은 μ•„λž˜μ™€ κ°™λ‹€
πŸ‘‰πŸ» i번째 κΉŒμ§€ 얻을 수 μžˆλŠ” μ‹λŸ‰μ˜ μ΅œλŒ€κ°’μ€ i-1λ²ˆμ§ΈκΉŒμ§€μ˜ μ΅œλŒ€κ°’κ³Ό i-2λ²ˆμ§ΈκΉŒμ§€μ˜ μ΅œλŒ€κ°’ + ν˜„μž¬ 창고의 μ‹λŸ‰κ°’ 쀑 더 큰 값이닀.

ν•œ μΉΈ 이상 떨어진 μ‹λŸ‰μ°½κ³ λŠ” 항상 ν„Έ 수 μžˆμœΌλ―€λ‘œ (i - 3)번째 μ΄ν•˜λŠ” κ³ λ €ν•  ν•„μš”κ°€ μ—†λ‹€.


python

# μ •μˆ˜ N을 μž…λ ₯ λ°›κΈ°
n = int(input())
# λͺ¨λ“  μ‹λŸ‰ 정보 μž…λ ₯ λ°›κΈ°
array = list(map(int, input().split()))

# μ•žμ„œ κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
d = [0] * 100 # n은 μ΅œλŒ€ 100κΉŒμ§€ λ“€μ–΄μ˜¬ 수 μžˆλ‹€ν–ˆμœΌλ―€λ‘œ

# λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°(Dynamic Programming) 진행 (보텀업)
d[0] = array[0]
d[1] = max(array[0], array[1]) 
for i in range(2, n):
    d[i] = max(d[i - 1], d[i - 2] + array[i])

# κ³„μ‚°λœ κ²°κ³Ό 좜λ ₯
print(d[n - 1])

Java

import java.util.*;

public class Main {

    // μ•žμ„œ κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™” 
    public static int[] d = new int[100];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // μ •μˆ˜ N을 μž…λ ₯λ°›κΈ°
        int n = sc.nextInt();

        // λͺ¨λ“  μ‹λŸ‰ 정보 μž…λ ₯λ°›κΈ°
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        // λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°(Dynamic Programming) 진행(보텀업)
        d[0] = arr[0];
        d[1] = Math.max(arr[0], arr[1]);
        for (int i = 2; i < n; i++) {
            d[i] = Math.max(d[i - 1], d[i - 2] + arr[i]);
        }

        // κ³„μ‚°λœ κ²°κ³Ό 좜λ ₯
        System.out.println(d[n - 1]);
    }
}



βœ”οΈ [μ‹€μŠ΅] 1둜 λ§Œλ“€κΈ° : 졜적 λΆ€λΆ„ ꡬ쑰, μ€‘λ³΅λ˜λŠ” λΆ€λΆ„ 문제, 보텀업

  • Xκ°€ 30000κΉŒμ§€μ΄λ―€λ‘œ λ‹Ήμ—°νžˆ DP μ‚¬μš©!!
  • μ™„μ „ 탐색 μ‹€μŠ΅ λ¬Έμ œμ—μ„œμ˜ 1이 될 λ•ŒκΉŒμ§€μ™€λŠ” λ‹€λ₯΄λ‹€. λ‹¨μˆœνžˆ 큰 κ°’μœΌλ‘œ λ‚˜λˆˆλ‹€κ³  μ—°μ‚° νšŸμˆ˜κ°€ μ΅œμ†Œκ°€ λ˜μ§„ μ•ŠκΈ° λ•Œλ¬Έ
  • λ”°λΌμ„œ 이 λ¬Έμ œλŠ” μž‘μ€ 문제λ₯Ό μ‘°ν•©ν•˜μ—¬ 큰 문제λ₯Ό ν•΄κ²°ν•˜κΈ° λ•Œλ¬Έμ— 졜적 λΆ€λΆ„ ꡬ쑰λ₯Ό λ§Œμ‘±ν•œλ‹€.

ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄ 문제λ₯Ό λ„μ‹ν™”ν•œ κ²ƒμ²˜λŸΌ ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜λŠ” 과정을 그림으둜 그렀보면 μ•„λž˜κ³Ό κ°™λ‹€.
βœ… 졜적 λΆ€λΆ„ ꡬ쑰와 μ€‘λ³΅λ˜λŠ” λΆ€λΆ„ 문제λ₯Ό λ§Œμ‘±ν•œλ‹€.

예λ₯Ό λ“€μ–΄ xκ°€ 6일 λ•ŒλŠ” 6μ—μ„œ 1을 λΊ€ f(5)μ—μ„œμ˜ 졜적의 ν•΄, 6μ—μ„œ 2λ₯Ό λ‚˜λˆˆ f(3)μ—μ„œμ˜ 졜적의 ν•΄, 6μ—μ„œ 3을 λ‚˜λˆˆ f(2)μ—μ„œμ˜ 졜적의 ν•΄ μ€‘μ—μ„œ κ°€μž₯ μž‘μ€ 값을 골라 f(6)일 λ•Œμ˜ 졜적의 ν•΄λ₯Ό ꡬ할 수 μžˆλ‹€.

λ‹€λ§Œ μ—¬κΈ°μ„œ 6은 5둜 λ‚˜λˆ„μ–΄λ–¨μ–΄μ§€μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 5둜 λ‚˜λˆ„λŠ” κ²½μš°λŠ” κ³ λ €ν•˜μ§€ μ•Šμ•˜λ‹€.


i번째 a = iλ₯Ό 1둜 λ§Œλ“€κΈ° μœ„ν•œ μ΅œμ†Œ μ—°μ‚° 횟수라고 μ •μ˜ ν–ˆμ„ λ•Œ, 점화식은 μ•„λž˜μ™€ κ°™λ‹€.

단, 1을 λΉΌλŠ” 연산을 μ œμ™Έν•˜κ³ λŠ” ν•΄λ‹Ή 수둜 λ‚˜λˆ„μ–΄λ–¨μ–΄μ§ˆ λ•Œμ— ν•œν•΄ 점화식을 μ μš©ν•  수 μžˆλ‹€.



python

# μ •μˆ˜ Xλ₯Ό μž…λ ₯ λ°›κΈ°
x = int(input())

# μ•žμ„œ κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
d = [0] * 1000001

# λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°(Dynamic Programming) 진행(보텀업)
for i in range(2, x + 1):
    # ν˜„μž¬μ˜ μˆ˜μ—μ„œ 1을 λΉΌλŠ” 경우
    d[i] = d[i - 1] + 1
    # ν˜„μž¬μ˜ μˆ˜κ°€ 2둜 λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€λŠ” 경우
    if i % 2 == 0:
        d[i] = min(d[i], d[i // 2] + 1)
    # ν˜„μž¬μ˜ μˆ˜κ°€ 3으둜 λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€λŠ” 경우
    if i % 3 == 0:
        d[i] = min(d[i], d[i // 3] + 1)
    # ν˜„μž¬μ˜ μˆ˜κ°€ 5둜 λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€λŠ” 경우
    if i % 5 == 0:
        d[i] = min(d[i], d[i // 5] + 1)

print(d[x])

python(μ§œμ™•.ver)

x = int(input())
dp = [0] * (x + 1)

for i in range(2, x + 1):
    arr = []
    if i % 2 == 0:
        arr.append(dp[i//2])
    if i % 3 == 0:
        arr.append(dp[i//3])
    if i % 5 == 0:
        arr.append(dp[i//5])
    arr.append(dp[i-1])
    dp[i] = int(min(arr)) + 1

print(dp[x])

Java

import java.util.*;

public class Main {

    // μ•žμ„œ κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™” 
    public static int[] d = new int[30001];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int x = sc.nextInt();

        // λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°(Dynamic Programming) 진행(보텀업)
        for (int i = 2; i <= x; i++) {
            // ν˜„μž¬μ˜ μˆ˜μ—μ„œ 1을 λΉΌλŠ” 경우
            d[i] = d[i - 1] + 1;
            // ν˜„μž¬μ˜ μˆ˜κ°€ 2둜 λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€λŠ” 경우
            if (i % 2 == 0)
                d[i] = Math.min(d[i], d[i / 2] + 1);
            // ν˜„μž¬μ˜ μˆ˜κ°€ 3으둜 λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€λŠ” 경우
            if (i % 3 == 0)
                d[i] = Math.min(d[i], d[i / 3] + 1);
            // ν˜„μž¬μ˜ μˆ˜κ°€ 5둜 λ‚˜λˆ„μ–΄ λ–¨μ–΄μ§€λŠ” 경우
            if (i % 5 == 0)
                d[i] = Math.min(d[i], d[i / 5] + 1);
        }
        System.out.println(d[x]);
    }
}



βœ”οΈ [μ‹€μŠ΅] 효율적인 화폐 ꡬ성 : 보텀업


문제 ν•΄κ²° 아이디어


N = 3, M = 7이고, 각 ν™”νμ˜ λ‹¨μœ„κ°€ 2, 3, 5인 경우λ₯Ό 확인해 보자

1️⃣ [Step 1 (μ΄ˆκΈ°ν™”)]

  • λ¨Όμ € 각 μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” κ°’μœΌλ‘œ INF(λ¬΄ν•œ)의 값을 μ„€μ •
  • INF은 νŠΉμ • κΈˆμ•‘μ„ λ§Œλ“€ 수 μžˆλŠ” 화폐 ꡬ성이 κ°€λŠ₯ν•˜μ§€ μ•Šλ‹€λŠ” 의미λ₯Ό 가진닀.
  • λ³Έ λ¬Έμ œμ—μ„œλŠ” 10,001을 μ‚¬μš©ν•  수 μžˆλ‹€. (M의 μ΅œλŒ€κ°’μ΄ 10000μ΄λ―€λ‘œ)

2️⃣ [Step 2]

  • 첫 번째 화폐 λ‹¨μœ„μΈ 2λ₯Ό 확인
  • 점화식에 λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 λ¦¬μŠ€νŠΈκ°€ κ°±μ‹ λœλ‹€.

3️⃣ [Step 3]

  • 두 번째 화폐 λ‹¨μœ„μΈ 3λ₯Ό 확인
  • 점화식에 λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 λ¦¬μŠ€νŠΈκ°€ κ°±μ‹ λœλ‹€.

4️⃣ [Step 4]

  • μ„Έ 번째 화폐 λ‹¨μœ„μΈ 5λ₯Ό 확인
  • 점화식에 λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 μ΅œμ’…μ μœΌλ‘œ λ¦¬μŠ€νŠΈκ°€ κ°±μ‹ λœλ‹€.

python

# μ •μˆ˜ N, M을 μž…λ ₯ λ°›κΈ°
n, m = map(int, input().split())
# N개의 화폐 λ‹¨μœ„ 정보λ₯Ό μž…λ ₯ λ°›κΈ°
array = []
for i in range(n):
    array.append(int(input()))

# ν•œ 번 κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
d = [10001] * (m + 1)

# λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°(Dynamic Programming) 진행(보텀업)
d[0] = 0
for i in range(n):  # i = 화폐 λ‹¨μœ„
    for j in range(array[i], m + 1):  # j = κΈˆμ•‘
        if d[j - array[i]] != 10001: # (i - k)원을 λ§Œλ“œλŠ” 방법이 μ‘΄μž¬ν•˜λŠ” 경우
            d[j] = min(d[j], d[j - array[i]] + 1)

# κ³„μ‚°λœ κ²°κ³Ό 좜λ ₯
if d[m] == 10001: # μ΅œμ’…μ μœΌλ‘œ M원을 λ§Œλ“œλŠ” 방법이 μ—†λŠ” 경우
    print(-1)
else:
    print(d[m])

Java

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // μ •μˆ˜ N, M을 μž…λ ₯λ°›κΈ°
        int n = sc.nextInt();
        int m = sc.nextInt();

        // N개의 화폐 λ‹¨μœ„ 정보λ₯Ό μž…λ ₯ λ°›κΈ°
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        // μ•žμ„œ κ³„μ‚°λœ κ²°κ³Όλ₯Ό μ €μž₯ν•˜κΈ° μœ„ν•œ DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™” 
        int[] d = new int[m + 1];
        Arrays.fill(d, 10001);

        // λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°(Dynamic Programming) 진행(보텀업)
        d[0] = 0;
        for (int i = 0; i < n; i++) {
            for (int j = arr[i]; j <= m; j++) {
                // (i - k)원을 λ§Œλ“œλŠ” 방법이 μ‘΄μž¬ν•˜λŠ” 경우
                if (d[j - arr[i]] != 10001) {
                    d[j] = Math.min(d[j], d[j - arr[i]] + 1);
                }
            }
        }

        // κ³„μ‚°λœ κ²°κ³Ό 좜λ ₯
        if (d[m] == 10001) { // μ΅œμ’…μ μœΌλ‘œ M원을 λ§Œλ“œλŠ” 방법이 μ—†λŠ” 경우
            System.out.println(-1);
        }
        else {
            System.out.println(d[m]);
        }
    }
}



βœ”οΈ [μ‹€μŠ΅] κΈˆκ΄‘ : 보텀업


문제 ν•΄κ²° 아이디어

  • κΈˆκ΄‘μ˜ λͺ¨λ“  μœ„μΉ˜μ— λŒ€ν•˜μ—¬ λ‹€μŒμ˜ μ„Έ κ°€μ§€λ§Œ κ³ λ €ν•˜λ©΄ λœλ‹€.
    1. μ™Όμͺ½ μœ„μ—μ„œ μ˜€λŠ” 경우
    2. μ™Όμͺ½ μ•„λž˜μ—μ„œ μ˜€λŠ” 경우
    3. μ™Όμͺ½μ—μ„œ μ˜€λŠ” 경우
  • μ„Έ 가지 경우 μ€‘μ—μ„œ κ°€μž₯ λ§Žμ€ κΈˆμ„ 가지고 μžˆλŠ” 경우λ₯Ό ν…Œμ΄λΈ”μ— κ°±μ‹ ν•΄μ£Όμ–΄ 문제λ₯Ό ν•΄κ²°ν•©λ‹ˆλ‹€.

  • array[i][j] = iν–‰ j열에 μ‘΄μž¬ν•˜λŠ” 금의 μ–‘
  • dp[i][j] = iν–‰ jμ—΄κΉŒμ§€μ˜ 졜적의 ν•΄ (얻을 수 μžˆλŠ” 금의 μ΅œλŒ“κ°’)
  • 점화식은 μ•„λž˜μ™€ κ°™λ‹€.

    dp[i][j] = array[i][j] + max(dp[i - 1][j - 1], dp[i][j - 1], dp[i + 1][j - 1])

  • μ΄λ•Œ ν…Œμ΄λΈ”μ— μ ‘κ·Όν•  λ•Œλ§ˆλ‹€ 리슀트의 λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜μ§€ μ•ŠλŠ”μ§€ 체크해야 ν•œλ‹€.

  • νŽΈμ˜μƒ 초기 데이터λ₯Ό λ‹΄λŠ” λ³€μˆ˜ arrayλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  λ°”λ‘œ DP ν…Œμ΄λΈ”μ— 초기 데이터λ₯Ό λ‹΄μ•„μ„œ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μ μš©ν•  수 μžˆλ‹€.


ν•΄κ²° κ³Όμ •


python

# ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€(Test Case) μž…λ ₯
for tc in range(int(input())):
    # κΈˆκ΄‘ 정보 μž…λ ₯
    n, m = map(int, input().split())
    array = list(map(int, input().split()))

    # λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μœ„ν•œ 2차원 DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
    dp = []
    index = 0
    for i in range(n):
    	# 0 ~ 3, 4 ~ 7 μ΄λ ‡κ²Œ μŠ¬λΌμ΄μ‹± ν•˜μ—¬ DP μ΄ˆκΈ°ν™”
        dp.append(array[index:index + m])
        index += m  # 4, 8, 12 μ΄λ ‡κ²Œ 증가

    # λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° 진행
    for j in range(1, m):
        for i in range(n):
            # μ™Όμͺ½ μœ„μ—μ„œ μ˜€λŠ” 경우
            if i == 0:  # 인덱슀 λ²—μ–΄λ‚œ 경우
                left_up = 0 
            else:
                left_up = dp[i - 1][j - 1]
            # μ™Όμͺ½ μ•„λž˜μ—μ„œ μ˜€λŠ” 경우
            if i == n - 1:  # 인덱슀 λ²—μ–΄λ‚œ 경우
                left_down = 0
            else:
                left_down = dp[i + 1][j - 1]
            # μ™Όμͺ½μ—μ„œ μ˜€λŠ” 경우
            left = dp[i][j - 1]
            dp[i][j] = dp[i][j] + max(left_up, left_down, left)

    result = 0
    # λ§ˆμ§€λ§‰ ν–‰μ˜ μ—΄(κ°€μž₯ 였λ₯Έμͺ½ μ—΄) 쀑 μ΅œλŒ€κ°’ κ³ λ₯΄κΈ°
    for i in range(n):
        result = max(result, dp[i][m - 1])

    print(result)

Java

import java.util.*;

public class Main {

    static int testCase, n, m;
    static int[][] arr = new int[20][20];
    static int[][] dp = new int[20][20];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€(Test Case) μž…λ ₯
        testCase = sc.nextInt();
        for (int tc = 0; tc < testCase; tc++) {
            // κΈˆκ΄‘ 정보 μž…λ ₯
            n = sc.nextInt();
            m = sc.nextInt();
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    arr[i][j] = sc.nextInt();
                }
            }
            // λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μœ„ν•œ 2차원 DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    dp[i][j] = arr[i][j];
                }
            }
            // λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° 진행
            for (int j = 1; j < m; j++) {
                for (int i = 0; i < n; i++) {
                    int leftUp, leftDown, left;
                    // μ™Όμͺ½ μœ„μ—μ„œ μ˜€λŠ” 경우
                    if (i == 0) leftUp = 0;
                    else leftUp = dp[i - 1][j - 1];
                    // μ™Όμͺ½ μ•„λž˜μ—μ„œ μ˜€λŠ” 경우
                    if (i == n - 1) leftDown = 0;
                    else leftDown = dp[i + 1][j - 1];
                    // μ™Όμͺ½μ—μ„œ μ˜€λŠ” 경우
                    left = dp[i][j - 1];
                    dp[i][j] = dp[i][j] + Math.max(leftUp, Math.max(leftDown, left));
                }
            }
            int result = 0;
            for (int i = 0; i < n; i++) {
                result = Math.max(result, dp[i][m - 1]);
            }
            System.out.println(result);
        }
    }
}



βœ”οΈ [μ‹€μŠ΅] 병사 λ°°μΉ˜ν•˜κΈ°


문제 ν•΄κ²° 아이디어

  • 이 문제의 κΈ°λ³Έ μ•„μ΄λ””μ–΄λŠ” κ°€μž₯ κΈ΄ μ¦κ°€ν•˜λŠ” λΆ€λΆ„ μˆ˜μ—΄(Longest Increasing Subsequence, LIS)둜 μ•Œλ €μ§„ μ „ν˜•μ μΈ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ° 문제의 아이디어닀.
  • 예λ₯Ό λ“€μ–΄ ν•˜λ‚˜μ˜ μˆ˜μ—΄ array = {4, 2, 5, 8, 4, 11, 15}이 μžˆλ‹€κ³  ν•˜μž.
    βœ… 이 μˆ˜μ—΄μ˜ κ°€μž₯ κΈ΄ μ¦κ°€ν•˜λŠ” λΆ€λΆ„ μˆ˜μ—΄μ€ {4, 5, 8, 11, 15}이닀.
    βœ… λ³Έ λ¬Έμ œλŠ” κ°€μž₯ κΈ΄ κ°μ†Œν•˜λŠ” λΆ€λΆ„ μˆ˜μ—΄μ„ μ°ΎλŠ” 문제둜 μΉ˜ν™˜ν•  수 μžˆμœΌλ―€λ‘œ, LIS μ•Œκ³ λ¦¬μ¦˜μ„ 쑰금 μˆ˜μ •ν•˜μ—¬ μ μš©ν•¨μœΌλ‘œμ¨ 정닡을 λ„μΆœν•  수 μžˆλ‹€.

κ°€μž₯ κΈ΄ μ¦κ°€ν•˜λŠ” λΆ€λΆ„ μˆ˜μ—΄(Longest Increasing Subsequence, LIS)

D[i] = array[i]λ₯Ό λ§ˆμ§€λ§‰ μ›μ†Œλ‘œ κ°€μ§€λŠ” λΆ€λΆ„ μˆ˜μ—΄μ˜ μ΅œλŒ€ 길이

점화식은 μ•„λž˜μ™€ κ°™λ‹€.


문제 ν•΄κ²° κ³Όμ •


κ°€μž₯ λ¨Όμ € μž…λ ₯ 받은 병사 μ •λ³΄μ˜ μˆœμ„œλ₯Ό λ’€μ§‘λŠ”λ‹€.
κ°€μž₯ κΈ΄ μ¦κ°€ν•˜λŠ” λΆ€λΆ„ μˆ˜μ—΄ (LIS) μ•Œκ³ λ¦¬μ¦˜μ„ μˆ˜ν–‰ν•˜μ—¬ 정닡을 λ„μΆœν•œλ‹€.

python

n = int(input())
array = list(map(int, input().split()))
# μˆœμ„œλ₯Ό 뒀집어 '졜μž₯ 증가 λΆ€λΆ„ μˆ˜μ—΄' 문제둜 λ³€ν™˜
array.reverse()

# λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μœ„ν•œ 1차원 DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
dp = [1] * n

# κ°€μž₯ κΈ΄ μ¦κ°€ν•˜λŠ” λΆ€λΆ„ μˆ˜μ—΄(LIS) μ•Œκ³ λ¦¬μ¦˜ μˆ˜ν–‰
for i in range(1, n):
    for j in range(0, i):
        if array[j] < array[i]:
            dp[i] = max(dp[i], dp[j] + 1)

# μ—΄μ™Έν•΄μ•Ό ν•˜λŠ” λ³‘μ‚¬μ˜ μ΅œμ†Œ 수λ₯Ό 좜λ ₯
print(n - max(dp))

Java

import java.util.*;

public class Main {

    static int n;
    static ArrayList<Integer> v = new ArrayList<Integer>();
    static int[] dp = new int[2000];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();

        for (int i = 0; i < n; i++) {
            v.add(sc.nextInt());
        }

        // μˆœμ„œλ₯Ό 뒀집어 '졜μž₯ 증가 λΆ€λΆ„ μˆ˜μ—΄' 문제둜 λ³€ν™˜
        Collections.reverse(v);

        // λ‹€μ΄λ‚˜λ―Ή ν”„λ‘œκ·Έλž˜λ°μ„ μœ„ν•œ 1차원 DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
        for (int i = 0; i < n; i++) {
            dp[i] = 1;
        }

        // κ°€μž₯ κΈ΄ μ¦κ°€ν•˜λŠ” λΆ€λΆ„ μˆ˜μ—΄(LIS) μ•Œκ³ λ¦¬μ¦˜ μˆ˜ν–‰
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (v.get(j) < v.get(i)) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
        }

        // μ—΄μ™Έν•΄μ•Ό ν•˜λŠ” λ³‘μ‚¬μ˜ μ΅œμ†Œ 수λ₯Ό 좜λ ₯
        int maxValue = 0;
        for (int i = 0; i < n; i++) {
            maxValue = Math.max(maxValue, dp[i]);
        }
        System.out.println(n - maxValue);
    }
}
profile
λ°±μ—”λ“œ 병아리 πŸ₯

0개의 λŒ“κΈ€