λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
μ•Œκ³ λ¦¬μ¦˜

[Java] BOJ 2579 계단 였λ₯΄κΈ°

by 🍊귀🍊 2024. 7. 27.

문제 

문제 링크 \https://www.acmicpc.net/problem/2579

  • 계단 였λ₯΄κΈ° κ²Œμž„μ€ 계단 μ•„λž˜ μ‹œμž‘μ λΆ€ν„° 계단 κΌ­λŒ€κΈ°μ— μœ„μΉ˜ν•œ λ„μ°©μ κΉŒμ§€ κ°€λŠ” κ²Œμž„μ΄λ‹€. <κ·Έλ¦Ό 1>κ³Ό 같이 각각의 κ³„λ‹¨μ—λŠ” μΌμ •ν•œ μ μˆ˜κ°€ μ“°μ—¬ μžˆλŠ”λ° 계단을 밟으면 κ·Έ 계단에 μ“°μ—¬ μžˆλŠ” 점수λ₯Ό μ–»κ²Œ λœλ‹€ 
    <κ·Έλ¦Ό 1>
  • 예λ₯Ό λ“€μ–΄ <κ·Έλ¦Ό 2>와 같이 μ‹œμž‘μ μ—μ„œλΆ€ν„° 첫 번째, 두 번째, λ„€ 번째, μ—¬μ„― 번째 계단을 λ°Ÿμ•„ 도착점에 λ„λ‹¬ν•˜λ©΄ 총 μ μˆ˜λŠ” 10 + 20 + 25 + 20 = 75점이 λœλ‹€.
    <κ·Έλ¦Ό 2>
  • 계단 였λ₯΄λŠ” λ°λŠ” λ‹€μŒκ³Ό 같은 κ·œμΉ™μ΄ μžˆλ‹€.
    1. 계단은 ν•œ λ²ˆμ— ν•œ 계단씩 λ˜λŠ” 두 계단씩 였λ₯Ό 수 μžˆλ‹€. 즉, ν•œ 계단을 λ°ŸμœΌλ©΄μ„œ μ΄μ–΄μ„œ λ‹€μŒ κ³„λ‹¨μ΄λ‚˜, λ‹€μŒ λ‹€μŒ κ³„λ‹¨μœΌλ‘œ 였λ₯Ό 수 μžˆλ‹€.
    2. μ—°μ†λœ μ„Έ 개의 계단을 λͺ¨λ‘ λ°Ÿμ•„μ„œλŠ” μ•ˆ λœλ‹€. 단, μ‹œμž‘μ μ€ 계단에 ν¬ν•¨λ˜μ§€ μ•ŠλŠ”λ‹€.
    3. λ§ˆμ§€λ§‰ 도착 계단은 λ°˜λ“œμ‹œ λ°Ÿμ•„μ•Ό ν•œλ‹€.
  • λ”°λΌμ„œ 첫 번째 계단을 밟고 이어 두 번째 κ³„λ‹¨μ΄λ‚˜, μ„Έ 번째 κ³„λ‹¨μœΌλ‘œ 였λ₯Ό 수 μžˆλ‹€.
  • ν•˜μ§€λ§Œ, 첫 번째 계단을 밟고 이어 λ„€ 번째 κ³„λ‹¨μœΌλ‘œ μ˜¬λΌκ°€κ±°λ‚˜, 첫 번째, 두 번째, μ„Έ 번째 계단을 μ—°μ†ν•΄μ„œ λͺ¨λ‘ λ°Ÿμ„ μˆ˜λŠ” μ—†λ‹€.
  • 각 계단에 μ“°μ—¬ μžˆλŠ” μ μˆ˜κ°€ μ£Όμ–΄μ§ˆ λ•Œ 이 κ²Œμž„μ—μ„œ 얻을 수 μžˆλŠ” 총 점수의 μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.
  • μž…λ ₯의 첫째 쀄에 κ³„λ‹¨μ˜ κ°œμˆ˜κ°€ 주어진닀.
  • λ‘˜μ§Έ 쀄뢀터 ν•œ 쀄에 ν•˜λ‚˜μ”© 제일 μ•„λž˜μ— 놓인 계단뢀터 μˆœμ„œλŒ€λ‘œ 각 계단에 μ“°μ—¬ μžˆλŠ” μ μˆ˜κ°€ 주어진닀. κ³„λ‹¨μ˜ κ°œμˆ˜λŠ” 300μ΄ν•˜μ˜ μžμ—°μˆ˜μ΄κ³ , 계단에 μ“°μ—¬ μžˆλŠ” μ μˆ˜λŠ” 10,000μ΄ν•˜μ˜ μžμ—°μˆ˜μ΄λ‹€.
  • 첫째 쀄에 계단 였λ₯΄κΈ° κ²Œμž„μ—μ„œ 얻을 수 μžˆλŠ” 총 점수의 μ΅œλŒ“κ°’μ„ 좜λ ₯ν•œλ‹€.

아이디어

  • 계단이 2κ°œμΌλ•ŒκΉŒμ§€λŠ” λͺ¨λ“  계단값을 더해주면 λ˜λ―€λ‘œ κ·Έλ ‡κ²Œ μ΄ˆκΈ°κ°’μ„ μ €μž₯ν•œλ‹€.
  • 계단이 3κ°œμΌλ•ŒλŠ” 1번 3번 계단 ν•©κ³Ό 2번 3번 계단 ν•© 쀑 μ–΄λ–€ 것이 더 큰지 λΉ„κ΅ν•΄μ„œ μ €μž₯ν•œλ‹€.
  • κ³„λ‹¨λ“€μ˜ 점수 합은 배열에 μ €μž₯ν•˜λŠ”λ° λ°°μ—΄μ˜ iλ²ˆμ§ΈλŠ” i번째 κ³„λ‹¨κΉŒμ§€μ˜ μ΅œλŒ“κ°’μ„ μ˜λ―Έν•œλ‹€.
  • 그리고 λ§ˆμ§€λ§‰ 계단은 무쑰건 λ°Ÿμ•„μ•Ό λ˜λ―€λ‘œ i번째 계단은 무쑰건 ν¬ν•¨ν•΄μ„œ 4번째 계단뢀터 N개의 κ³„λ‹¨κΉŒμ§€ λ°˜λ³΅ν•œλ‹€.
  • i번째 κ³„λ‹¨κΉŒμ§€μ˜ μ΅œλŒ“κ°’μ„ κ΅¬ν• λ•Œ, i번째 계단 + (i-1)번째 계단에 i-3λ²ˆμ§ΈκΉŒμ§€μ˜ μ΅œλŒ“κ°’μ„ λ”ν•œ κ°’κ³Ό i번째 계단 + i-2λ²ˆμ§ΈκΉŒμ§€μ˜ μ΅œλŒ“κ°’μ„ λ”ν•œ κ°’ 쀑 더 큰 값을 μ €μž₯ν•œλ‹€. (μ—°μ†μœΌλ‘œ 3개의 계단을 λ°Ÿμ„ 수 μ—†μœΌλ―€λ‘œ i번째 계단을 κΈ°μ€€μœΌλ‘œ 연속 λ‘κ°œμ˜ 계단을 λ°Ÿμ€ 것과 ν•œκ°œμ˜ 계단을 λ°Ÿμ€ 것을 비ꡐ)

κ²ͺ은 μ‹œν–‰μ°©μ˜€

  • 이 문제λ₯Ό 처음 λ΄€μ„λ•Œ, 'dp둜 ν’€μ–΄μ•Όλ˜κ² λ‹€..!' 생각을 ν•˜κ³  식을 μ„Έμ›Œλ³΄λ €κ³  ν•˜μ˜€λ‹€.
  • 식을 μ–΄λŠμ •λ„ λŒ€κ°• μ„Έμ›Œλ³΄μ•˜μ§€λ§Œ, λ§ˆμ§€λ§‰ 계단을 무쑰건 λ°Ÿμ•„μ•Ό λœλ‹€λŠ” 점과 κ³„λ‹¨λ“€μ˜ 점수 ν•© 쀑 μ΅œλŒ“κ°’μ„ μ–΄λ–»κ²Œ μ°Ύμ§€λΌλŠ” λ”œλ ˆλ§ˆμ— 빠지며... λ¬Έμ œκ°€ μ•ˆν’€λ Έλ‹€...
  • κ²°κ΅­ 정말 λ§Žμ€ 고민을 ν•˜λ‹€κ°€ 풀이λ₯Ό ν•œλ²ˆ 읽고 λ‹€μ‹œ ν’€κ²Œ λ˜μ—ˆλ‹€ γ…œγ…œγ…œ
  • μ›¬λ§Œν•˜λ©΄ 풀이λ₯Ό 보지 μ•Šκ³  문제λ₯Ό ν’€λ €κ³  ν–ˆμ§€λ§Œ... ν•΄λ‹Ή λ¬Έμ œλŠ” 방법이 정말 μ œλŒ€λ‘œ 생각이 λ‚˜μ§€ μ•Šμ•„μ„œ μ–΄μ©” 수 없이 λ³΄μ•˜λ‹€...
  • κ·Έλž˜λ„ 풀이보고 λ‹€μ‹œ ν’€λ©΄μ„œ 주석을 ν•˜λ‚˜ν•˜λ‚˜ μ„Έμ„Έν•˜κ²Œ λ‹¬λ©΄μ„œ μ œλŒ€λ‘œ 이해해보렀고 ν–ˆλ‹€.
  • 이 정도면 μ‰¬μš΄ dpλ¬Έμ œμΌν…λ° 벌써 μ–΄λ €μ›Œν•˜λ‹ˆ... μ•žμœΌλ‘œ 남은 dpλ¬Έμ œλ“€μ΄ κ±±μ •λ˜μ§€λ§Œ μ΄λ²ˆκΈ°νšŒμ— dpλ₯Ό μ œλŒ€λ‘œ μ΄ν•΄ν•΄μ„œ λ‹€μŒλΆ€ν„°λŠ” μ΅œλŒ€ν•œ λ‚΄ 힘으둜 ν’€μ–΄μ•Όκ² λ‹€..! (ν¬κΈ°ν•˜μ§€ 말기..!!)

ν¬κΈ°ν•˜μ§€ 말고 νŒŒμ΄νŒ…ν•˜μž!!

μ½”λ“œ

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

public class BOJ2579 {
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine());

        // 계단 점수 μ €μž₯ λ°°μ—΄
        int stairs[] = new int[N + 1];

        // κ³„λ‹¨μ˜ μ μˆ˜λ“€μ„ λ”ν•œ λ°°μ—΄
        int scores[] = new int[N + 1];

        for(int i = 1; i <= N; i++){
            int s = Integer.parseInt(br.readLine());

            // 계단 점수 μ €μž₯
            stairs[i] = s;
        }

        // 계단이 ν•œκ°œμΌ λ•Œ, 계단 ν•œκ°œμ˜ 점수만 λ”ν•˜λ©΄λ¨
        if(N == 1){
            scores[1] = stairs[1];
        }
        // 계단이 λ‘κ°œμΌ λ•Œ, 계단 λ‘κ°œμ˜ 점수만 λ”ν•˜λ©΄λ¨
        else if(N == 2){
            scores[2] = stairs[1] + stairs[2];
        }
        // 계단이 3개 이상일 경우,
        else{
            // 1번째 κ³„λ‹¨κΉŒμ§€ 졜고 μ μˆ˜λŠ” 1번 계단 점수만
            scores[1] = stairs[1];
            // 2번째 κ³„λ‹¨κΉŒμ§€ 졜고 μ μˆ˜λŠ” 1번 계단 + 2번 계단 점수
            scores[2] = stairs[1] + stairs[2];
            // 3번째 κ³„λ‹¨κΉŒμ§€ 졜고 μ μˆ˜λŠ” 3개의 계단을 μ—°μ†ν•΄μ„œ 밟으면 μ•ˆλ˜λ―€λ‘œ
            // 1번 + 3번과 2번 + 3번 쀑 더 큰 κ°’μœΌλ‘œ μ €μž₯
            scores[3] = Math.max(stairs[1] + stairs[3], stairs[2] + stairs[3]);

            // 4번째 계단뢀터 N번째 κ³„λ‹¨κΉŒμ§€ 반볡
            for(int i = 4; i < N + 1; i++){
                // 끝에 계단은 무쑰건 밝아야됨
                // ν˜„μž¬ 계단을 κΈ°μ€€μœΌλ‘œ 연속 λ‘μΉΈμœΌλ‘œ λ°Ÿμ„μ§€ ν•œμΉΈμœΌλ‘œ λ°Ÿμ„μ§€μ— 따라 비ꡐ
                // ν˜„μž¬ 계단을 κΈ°μ€€μœΌλ‘œ μ—°μ†ν•΄μ„œ 두칸을 λ°ŸλŠ”λ‹€λ©΄
                // i번째 계단 + i-1번째 계단에 i-3번째 κ³„λ‹¨κΉŒμ§€μ˜ μ΅œλŒ€κ°’μ„ λ”ν•œ κ°’,
                // ν˜„μž¬ 계단을 κΈ°μ€€μœΌλ‘œ μ—°μ†ν•΄μ„œ ν•œμΉΈμ„ λ°ŸλŠ”λ‹€λ©΄
                // i번째 계단 + i-2번째 κ³„λ‹¨κΉŒμ§€μ˜ μ΅œλŒ€κ°’μ„ λ”ν•œ 값이 λ‚˜μ˜€λŠ”λ°
                // μœ„ 값듀을 λΉ„κ΅ν•΄μ„œ 더 큰 값을 ν•΄λ‹Ή i번째 κ³„λ‹¨κΉŒμ§€μ˜ μ΅œλŒ€κ°’μ— μ €μž₯
                scores[i] = Math.max(scores[i - 3] + stairs[i - 1] + stairs[i], scores[i - 2] + stairs[i]);
            }
        }

        System.out.println(scores[N]);
    }
}