Algorithm 2023. 6. 22.

[Programmers, Lv.2] λ•…λ”°λ¨ΉκΈ° (feat. λ™μ κ³„νšλ²•, μžλ°”μŠ€ν¬λ¦½νŠΈ)

문제 μ„€λͺ…

λ•…λ”°λ¨ΉκΈ° κ²Œμž„μ„ ν•˜λ €κ³  ν•©λ‹ˆλ‹€. λ•…λ”°λ¨ΉκΈ° κ²Œμž„μ˜ λ•…(land)은 총 Nν–‰ 4μ—΄λ‘œ 이루어져 있고, λͺ¨λ“  μΉΈμ—λŠ” μ μˆ˜κ°€ μ“°μ—¬ μžˆμŠ΅λ‹ˆλ‹€. 1ν–‰λΆ€ν„° 땅을 밟으며 ν•œ ν–‰μ”© λ‚΄λ €μ˜¬ λ•Œ, 각 ν–‰μ˜ 4μΉΈ 쀑 ν•œ 칸만 λ°ŸμœΌλ©΄μ„œ 내렀와야 ν•©λ‹ˆλ‹€. 단, λ•…λ”°λ¨ΉκΈ° κ²Œμž„μ—λŠ” ν•œ ν–‰μ”© λ‚΄λ €μ˜¬ λ•Œ, 같은 열을 μ—°μ†ν•΄μ„œ λ°Ÿμ„ 수 μ—†λŠ” 특수 κ·œμΉ™μ΄ μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€λ©΄,

| 1 | 2 | 3 | 5 |

| 5 | 6 | 7 | 8 |

| 4 | 3 | 2 | 1 |

둜 땅이 μ£Όμ–΄μ‘Œλ‹€λ©΄, 1ν–‰μ—μ„œ λ„€λ²ˆμ§Έ μΉΈ (5)λ₯Ό λ°Ÿμ•˜μœΌλ©΄, 2ν–‰μ˜ λ„€λ²ˆμ§Έ μΉΈ (8)은 λ°Ÿμ„ 수 μ—†μŠ΅λ‹ˆλ‹€.

λ§ˆμ§€λ§‰ ν–‰κΉŒμ§€ λͺ¨λ‘ 내렀왔을 λ•Œ, 얻을 수 μžˆλŠ” 점수의 μ΅œλŒ€κ°’μ„ returnν•˜λŠ” solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄ μ£Όμ„Έμš”. μœ„ 예의 경우, 1ν–‰μ˜ λ„€λ²ˆμ§Έ μΉΈ (5), 2ν–‰μ˜ μ„Έλ²ˆμ§Έ μΉΈ (7), 3ν–‰μ˜ 첫번째 μΉΈ (4) 땅을 λ°Ÿμ•„ 16점이 졜고점이 λ˜λ―€λ‘œ 16을 return ν•˜λ©΄ λ©λ‹ˆλ‹€.

μ œν•œμ‚¬ν•­

  • ν–‰μ˜ 개수 N : 100,000 μ΄ν•˜μ˜ μžμ—°μˆ˜
  • μ—΄μ˜ κ°œμˆ˜λŠ” 4개이고, λ•…(land)은 2차원 λ°°μ—΄λ‘œ μ£Όμ–΄μ§‘λ‹ˆλ‹€.
  • 점수 : 100 μ΄ν•˜μ˜ μžμ—°μˆ˜

μž…μΆœλ ₯ 예

land answer
[[1,2,3,5],[5,6,7,8],[4,3,2,1]] 16

문제 풀이

이 λ¬Έμ œλŠ” λ™μ κ³„νšλ²•μ„ 톡해 풀이할 수 μžˆμŠ΅λ‹ˆλ‹€. (μžλ°”μŠ€ν¬λ¦½νŠΈ μ™Έμ˜ μ–Έμ–΄λ‘œ ν’€ 경우 μ™„μ „νƒμƒ‰μœΌλ‘œλ„ 풀이가 κ°€λŠ₯ν•˜μ§€λ§Œ, μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œλŠ” μ‹œκ°„ ν•œκ³„λ‘œ 인해 λ™μ κ³„νšλ²•λ§Œ κ°€λŠ₯ν•œ κ²ƒμœΌλ‘œ μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€..πŸ˜‚ )

λ™μ κ³„νšλ²•μ΄λž€?

λ™μ κ³„νšλ²•(Dynamic Programming, aka DP)은 기본적인 μ•„μ΄λ””μ–΄λ‘œ ν•˜λ‚˜μ˜ 큰 문제λ₯Ό μ—¬λŸ¬ 개의 μž‘μ€ 문제둜 λ‚˜λˆ„μ–΄μ„œ κ·Έ κ²°κ³Όλ₯Ό μ €μž₯ν•˜μ—¬ λ‹€μ‹œ 큰 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 풀이 방식을 μ˜λ―Έν•©λ‹ˆλ‹€. 즉 νŠΉμ • μ•Œκ³ λ¦¬μ¦˜μ΄λΌκΈ° λ³΄λ‹€λŠ” ν•˜λ‚˜μ˜ 문제 ν•΄κ²° νŒ¨λŸ¬λ‹€μž„μœΌλ‘œ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

μ™œ λ™μ κ³„νšλ²•μ„ μ‚¬μš©ν• κΉŒ

λ™μ κ³„νšλ²•μ„ μ‚¬μš©ν•˜λŠ” μ΄μœ λ‘œλŠ” 일반적인 μž¬κ·€μ˜ ν•œκ³„λ₯Ό κ·Ήλ³΅ν•˜κΈ° μœ„ν•΄μ„œμž…λ‹ˆλ‹€. νŠΉμ • 횟수둜 반볡된 μž¬κ·€ν•¨μˆ˜μ˜ 값을 ꡬ해야 ν•  λ•Œ, ν•΄λ‹Ή μž¬κ·€ν•¨μˆ˜λ₯Ό ν•„μš”ν•  λ•Œ λ§ˆλ‹€ λ°˜λ³΅ν•˜κ²Œ 되면 μ—„μ²­λ‚œ μ‹œκ°„μ΄ μ†Œμš”λ©λ‹ˆλ‹€. 이미 ν•œλ²ˆ κ·Έ 닡을 κ΅¬ν•œ 적이 μžˆμŒμ—λ„ λΆˆκ΅¬ν•˜κ³  말이죠.

이에 λ°˜ν•΄ ν•œλ²ˆ κ΅¬ν•œ νŠΉμ • 횟수의 μž¬κ·€ν•¨μˆ˜ 값을 κΈ°μ–΅ν•΄λ’€λ‹€κ°€, λ‹€μŒ μž¬κ·€μ—μ„œ 이전에 κ΅¬ν–ˆλ˜ μž¬κ·€ν•¨μˆ˜ 값을 μ΄μš©ν•˜λŠ” 방식을 μ΄μš©ν•˜λ©΄ μ†Œμš”λ˜λŠ” μ‹œκ°„μ„ 획기적으둜 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ λ™μ κ³„νšλ²•μ€ 큰 문제λ₯Ό μž‘μ€ 문제둜 μͺΌκ°œμ–΄ μ •λ³΅ν•΄λ‚˜κ°€λŠ” λ°©μ‹μœΌλ‘œ 문제λ₯Ό ν’€μ΄ν•©λ‹ˆλ‹€.

λŒ€ν‘œμ μΈ λ™μ κ³„νšλ²• 풀이

λ‘œλŠ” ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ΄ μžˆμŠ΅λ‹ˆλ‹€.

μ•„λž˜μ™€ 같이 f(n) = f(n-1) + f(n-2)κ°€ λ°˜λ³΅λ˜λŠ” μˆ˜μ—΄μ„ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ΄λΌκ³  ν•©λ‹ˆλ‹€.

λ§Œμ•½ 100번째 ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μ„ κ΅¬ν•˜κΈ° μœ„ν•΄μ„  μž¬κ·€λ₯Ό λͺ‡λ²ˆμ΄λ‚˜ λ°˜λ³΅ν•΄μ•Ό ν• κΉŒμš”? 맀 ν”Όλ³΄λ‚˜μΉ˜ 수λ₯Ό ꡬ할 λ•Œ λ§ˆλ‹€ μž¬κ·€κ°€ κΈ°ν•˜κΈ‰μˆ˜μ μœΌλ‘œ λŠ˜μ–΄λ‚˜κ²Œ 되며, 100λ²ˆμ§Έμ— λ‹¬ν–ˆμ„ λ•ŒλŠ” μ•½ 7ν•΄ ####κ²½ ####μ‘° ... 번 이상 ν•¨μˆ˜κ°€ ν˜ΈμΆœλœλ‹€κ³  ν•©λ‹ˆλ‹€.

μ•„λ§ˆ 컴퓨터도 μ£½κ² μ£ ..? πŸ˜‚

μ΄λŸ¬ν•œ μƒν™©μ—μ„œ λ™μ κ³„νšλ²•μ„ μ΄μš©ν•˜λ©΄ 획기적으둜 μž¬κ·€ 횟수λ₯Ό 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€. 100번째 μˆ˜μ— 도달할 λ•Œ κΉŒμ§€ κ·Έ μ§μ „μ˜ ν”Όλ³΄λ‚˜μΉ˜ 수λ₯Ό κΈ°μ–΅ν•˜μ—¬, κΈ°μ–΅λœ μ „ ν”Όλ³΄λ‚˜μΉ˜ 수λ₯Ό μ΄μš©ν•˜μ—¬ λ‹€μŒ ν”Όλ³΄λ‚˜μΉ˜ 수λ₯Ό κ΅¬ν•œλ‹€λ©΄, 0(n) μ‹œκ°„λ³΅μž‘λ„λ‘œ 100번째 ν”Όλ³΄λ‚˜μΉ˜ 수λ₯Ό ꡬ할 수 μžˆμŠ΅λ‹ˆλ‹€.


μ΄λ ‡κ²Œ μ•½ 7ν•΄…의 μž¬κ·€ 횟수λ₯Ό 98번으둜 μ€„μ΄λŠ” 것을 톡해 λ™μ κ³„νšλ²•μ˜ λŠ₯λ ₯(?)을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

문제 풀이 μ½”λ“œ (μžλ°”μŠ€ν¬λ¦½νŠΈ)

λ‹€μ‹œ 문제둜 λŒμ•„μ™€μ„œ, 이번 λ•…λ”°λ¨ΉκΈ° λ¬Έμ œλ„ λ™μ κ³„νšλ²•μ„ μ΄μš©ν•΄μ„œ 풀이할 수 μžˆμŠ΅λ‹ˆλ‹€.


이 λ¬Έμ œμ—μ„œ ν•„μš”ν•œ 닡은 였직 ‘μ΅œλŒ€μ˜ κ°’’μž…λ‹ˆλ‹€. λ”°λΌμ„œ 이전 λ•…μ—μ„œ κ°€λŠ₯ν•œ μ΅œλŒ€μ˜ 값을 미리 μ €μž₯ν•΄λ‘μ—ˆλ‹€κ°€, λ‹€μŒ λ•…μœΌλ‘œ 이동할 λ•Œ 미리 μ €μž₯ν•΄λ‘” 이전 λ•…μ˜ μ΅œλŒ€μ˜ 값을 μ΄μš©ν•˜μ—¬ λ‹€μŒ μ΅œλŒ€μ˜ 값을 κ΅¬ν•˜λŠ” 방식을 μ΄μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.


이전 λ•…μ˜ 값에 λ‹€μŒ μ΅œλŒ€ 값을 더할 λ•ŒλŠ”, 같은 인덱슀의 땅은 λ°Ÿμ„ 수 μ—†λ‹€λŠ” κ·œμΉ™μ„ λ°˜μ˜ν•˜μ—¬, ν˜„μž¬ 인덱슀 μ™Έμ˜ λ‚˜λ¨Έμ§€ λ•…μ˜ κ°’λ“€ 쀑 μ΅œλŒ€ 값을 더해주면 λ©λ‹ˆλ‹€.



μœ„μ˜ 풀이λ₯Ό μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œλ‘œ ν’€λ©΄ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

const solution = land => 
     Math.max(...land.reduce((a, c) => 
        [
            c[0] + Math.max(a[1], a[2], a[3]),  
            c[1] + Math.max(a[0], a[2], a[3]),
            c[2] + Math.max(a[0], a[1], a[3]),
            c[3] + Math.max(a[0], a[1], a[2]),
        ];
    , [0, 0, 0, 0]);


λ‹€λ§Œ μœ„μ˜ μ½”λ“œλŠ” 맀 λ•…μ˜ κ°œμˆ˜κ°€ 4개둜 μ •ν•΄μ Έ μžˆλ‹€λŠ” ν•œκ³„κ°€ μžˆμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή ν•œκ³„λ₯Ό κ·Ήλ³΅ν•΄μ„œ, λ•…μ˜ κ°œμˆ˜μ— μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•  수 μžˆλŠ” μ½”λ“œλ‘œ λ¦¬νŒ©ν† λ§ν•˜λ©΄ μ•„λž˜ μ½”λ“œμ™€ κ°™μŠ΅λ‹ˆλ‹€.

const solution = (land) =>
  Math.max(
    ...land.reduce(
      (a, c) =>
        c.map((v, i) => v + Math.max(...a.filter((_, aIdx) => i !== aIdx))),
      [0, 0, 0, 0]
    )
  );