문제 링크

문제 요약

  1. 계단을 오르면서, 밟는 계단에 적혀있는 점수를 얻을 수 있다.
  2. 계단은 한번에 한 칸씩 또는 두 칸씩 오를 수 있다.
  3. 연속된 세 개의 계단을 모두 밟을 수 없다. 단, 시작점은 포함되지 않는다.
  4. 마지막 계단은 반드시 밟아야 한다.

풀이

어찌되었든, 구해야하는 것은 최대 점수입니다.

그럼 계단을 밟아야 하고, i번째 계단까지 밟았을 때까지 얻을 수 있는 최대 점수를 구해나가야 합니다.

일단 아래와 같이 DP식을 만들어볼 수 있습니다.

D[i] = i번째 계단까지 밟았을 때, 얻을 수 있는 최대 점수
 
D[i] = A[i] + max(D[i - 1], D[i - 2)
// A[i] 는 i번째 계단을 밟았을 때 얻는 점수입니다.

이제 문제가 생깁니다. 위 DP 식에는 연속된 세 개의 계단을 밟을 수 없다는 조건이 없다. 이 조건을 추가하여 DP식을 개량해야 합니다. 그럼, i번째 계단까지 올라왔을 때, 이전에 몇 개의 연속된 계단을 밟았는지 체크해봅시다.

D[i][j] = i번째 계단까지 이전에 j번 연속되어 밟았을 때, 얻을 수 있는 최대 점수
 
D[1][0] = ar[1]; 
D[1][1] = ar[1]; // 시작점은 계단에 포함되지 않습니다.
 
D[i][0] = A[i] + max(D[i - 2][0], D[i - 2][1]); // i번째 계단까지 밟았을 때, 1번 연속되어 밟았다는 이야기이고 즉, 이전에 건너뛰어 올랐다는 이야기입니다.
D[i][1] = A[i] + D[i - 1][0];

정답 코드

#include <bits/stdc++.h>
 
using namespace std;
 
int N;
int ar[330];
int D[330][2];
 
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
 
  cin >> N;
 
  for(int i = 1; i <= N; i++) cin >> ar[i];
 
  D[1][0] = ar[1];
  D[1][1] = ar[1];
 
  for(int i = 2; i <= N; i++) {
    D[i][0] = ar[i] + max(D[i-2][0], D[i-2][1]);
    D[i][1] = ar[i] + D[i-1][0];
  }
 
  cout << max(D[N][0], D[N][1]);
}

연관 페이지

참고 문헌 / 사이트