📚 문제
[BOJ C++] 백준 2579번: 계단 오르기
https://www.acmicpc.net/problem/2579

📝 입력 및 출력

🔎 문제 풀이
v 에는 각 계단에 쓰여있는 점수 자체를, dp에는 각 계단까지의 누적 최대 점수를 저장한다. 첫 번째 계단은 계단에 쓰인 점수 자체가 최댓값이고, 두 번째 계단은 첫 번째 계단의 점수 + 두 번째 계단의 점수가 최댓값이 된다. (각 계단의 점수는 자연수이므로 숫자 1개보단 2개를 더한 값이 당연히 더 크기 때문.)
세 번째 계단부터는 dp를 활용하여 문제를 해결할 수 있다.
- 1칸 + 2칸
- 2칸 + 1칸
- 1칸 + 1칸 + 1칸 ( X )
위와 같이 세 가지 방법으로 나누어 볼 수 있지만, 이 문제에서 3번 방법은 허용하지 않는다.
네 번째 계단에서는
- 1칸 + 1칸 + 1칸 + 1칸 ( X )
- 1칸 + 1칸 + 2칸
- 1칸 + 2칸 + 1칸
- 2칸 + 1칸 + 1칸
- 2칸 + 2칸
이 가능한데, 1번 방법은 4번이나 연속하기 때문에 불가능하다. 1번 경우를 제외하고 다른 경우들을 다시 잘 살펴보면
- (1칸 + 1칸) + 2칸
- (1칸 + 2칸) + 1칸
- (2칸 + 1칸) + 1칸
- (2칸) + 2칸
와 같이 묶을 수 있고, 2번 계단에서 두 칸 올라가는 경우(2, 5)와 3번 계단에서 한 칸 올라가는 경우(3, 4)로 해석할 수 있다.
즉, 계단을 오를 때 최대 점수를 얻는 방법은
1️⃣ 직전 계단을 밟고 올라오는 경우
2️⃣ 두 계단 전에서 건너뛰고 올라오는 경우
로 나눌 수 있고, 이를 바탕으로 점화식을 도출할 수 있다.
1️⃣ 직전 계단을 밟고 올라오는 경우
dp[i] = dp[i - 3] + v[i - 1] + v[i];
2️⃣ 두 계단 전에서 건너뛰고 올라오는 경우
dp[i] = dp[i - 2] + v[i];
따라서 i번 계단의 누적 점수가 최대가 되기 위해서는 두 값 중 더 큰 값을 선택하여 dp[i]에 저장하면 된다.
⌨️ C++ 코드
#include <bits/stdc++.h>
using namespace std;
int main(void) {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin >> n;
vector<int> v(n + 1), dp(n+1);
for (int i = 1; i <= n; i++) cin >> v[i];
dp[1] = v[1];
dp[2] = v[1] + v[2];
for (int i = 3; i <= n; i++) { // 바닥부터 시작.
dp[i] = max(dp[i - 2] + v[i], dp[i - 3] + v[i - 1] + v[i]); // 한 칸 - 두 칸 올라가기, 두 칸 올라가기.
}
cout << dp[n];
}
'백준 문제풀이' 카테고리의 다른 글
| [BOJ C++] 백준 31529번: 2024년에는 혼자가 아니길 (0) | 2025.09.19 |
|---|---|
| [BOJ C++] 백준 32653번: 흑백 요리사 (0) | 2025.09.10 |
| [BOJ C++] 백준 2609번: 최대공약수와 최소공배수 (0) | 2025.09.10 |
| [BOJ C++] 백준 13305번: 주유소 (0) | 2025.09.07 |
| [BOJ C++] 백준 2828번: 사과 담기 게임 (0) | 2025.09.07 |