계단 오르기
20 July 2019
문제 : https://www.acmicpc.net/problem/2579
이번은 i번째 계단에 오를 때, 몇 개의 연속한 계단을 올랐는지를 고려하는 문제를 풀어보도록 하겠습니다.
#include<stdio.h>
#define MAX(a,b) (((a)>(b))?(a):(b))
static int** arr;
int main(void) {
int N, val;
scanf("%d", &N);
arr = new int*[N];
for (int i = 0; i < N; i++)
{
scanf("%d", &val);
arr[i] = new int[2];
if (i == 0)
{
arr[i][0] = val;
arr[i][1] = val;
}
else if (i == 1) {
arr[i][0] = val;
arr[i][1] = arr[i - 1][0] + val;
}
else {
arr[i][0] = MAX(arr[i - 2][1], arr[i - 2][0]) + val;
arr[i][1] = arr[i - 1][0] + val;
}
}
printf("%d\n", MAX(arr[N-1][0], arr[N-1][1]));
return 0;
}
먼저 문제의 조건을 보도록 하겠습니다.계단은 한칸 또는 두칸씩 오를 수 있고, 대신 연속으로 세칸을 오를 수는 없습니다.
즉, 두칸을 오르는 경우는 그 다음 칸에서 한칸과 두칸을 모두 오를 수 있고, 한칸을 오르는 경우는 그 다음 칸에서 한칸만 오를 수가 있습니다.
해당 칸에서 연속 두칸을 사용하였는지 아닌지, 혹은 앞으로 한칸을 더 오를 수 있는지 없는지를 표시하기 위해 배열로 아래와 같이 작성해보도록 하겠습니다.
arr[i][0] = 연속 두칸을 사용하지 않은 경우 = 이전 칸이 두 칸 전일 때
arr[i][1] = 연속 두칸을 사용한 경우 = 이전 칸이 한칸 전일때
arr[i][0] = MAX(arr[i - 2][1], arr[i - 2][0]) + val;
arr[i][1] = arr[i - 1][0] + val;
위 코드에서 살펴보면, 바로 앞 칸이 두칸 전일때는 해당 칸에서 연속이든 아니든 상관이 없기때문에 연속일때 최대값(arr[i][1])과 연속이 아닐때 최대값(arr[i][0])을 모두 찾아와 비교하게 됩니다.바로 앞칸이 한칸 전일때는 연속이지 않은 칸만을 이어서 오를 수 있으므로 연속이 아닐때 최대값(arr[i][0])을 가져와 최대값을 설정하도록 합니다.
마지막 칸까지 업데이트하고 나서 두개 중에 최대인 값을 출력해주도록 합니다.