https://www.acmicpc.net/problem/2579
계단 오르기 성공
시간 제한메모리 제한제출정답맞은 사람정답 비율
1 초 | 128 MB | 50095 | 20106 | 14701 | 39.415% |
문제
계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. <그림 1>과 같이 각각의 계단에는 일정한 점수가 쓰여 있는데 계단을 밟으면 그 계단에 쓰여 있는 점수를 얻게 된다.
예를 들어 <그림 2>와 같이 시작점에서부터 첫 번째, 두 번째, 네 번째, 여섯 번째 계단을 밟아 도착점에 도달하면 총 점수는 10 + 20 + 25 + 20 = 75점이 된다.
계단 오르는 데는 다음과 같은 규칙이 있다.
- 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다.
- 연속된 세 개의 계단을 모두 밟아서는 안 된다. 단, 시작점은 계단에 포함되지 않는다.
- 마지막 도착 계단은 반드시 밟아야 한다.
따라서 첫 번째 계단을 밟고 이어 두 번째 계단이나, 세 번째 계단으로 오를 수 있다. 하지만, 첫 번째 계단을 밟고 이어 네 번째 계단으로 올라가거나, 첫 번째, 두 번째, 세 번째 계단을 연속해서 모두 밟을 수는 없다.
각 계단에 쓰여 있는 점수가 주어질 때 이 게임에서 얻을 수 있는 총 점수의 최댓값을 구하는 프로그램을 작성하시오.
입력
입력의 첫째 줄에 계단의 개수가 주어진다.
둘째 줄부터 한 줄에 하나씩 제일 아래에 놓인 계단부터 순서대로 각 계단에 쓰여 있는 점수가 주어진다. 계단의 개수는 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10,000이하의 자연수이다.
출력
첫째 줄에 계단 오르기 게임에서 얻을 수 있는 총 점수의 최댓값을 출력한다.
예제 입력 1 복사
6 10 20 15 25 10 20
예제 출력 1 복사
75
출처
Olympiad > 한국정보올림피아드 > 한국정보올림피아드시․도지역본선 > 지역본선 2006 > 초등부 4번
- 문제의 오타를 찾은 사람: cjswodmlskfk eric00513
문제 접근
규칙에 의거하여 점화식을 세우자.
- 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다.
- 연속된 세 개의 계단을 모두 밟아서는 안 된다. 단, 시작점은 계단에 포함되지 않는다.
- 마지막 도착 계단은 반드시 밟아야 한다.
마지막 계단까지의 최대 값으로, 마지막 항을 N으로 두었다.
3번의 조건에 의해 안밟는 경우는 제외하고
마지막 계단을 밟기 바로 전 상태를 조건으로 둔다.
1. 바로 전전 단계에서 2단점프로 N에 도착하는 시점
2. 바로 전 단계에서 1단점프로 N에 도착하는 시점
1번의 점화식은 바로 전 단계의 누적 점수를 dp[n-2]로 정의( 끝 항이 n이 라고 가정)
-> dp[n] (누적점수) = dp[n-2]+score_arr[n] (전전 상태의 누적합 + 끝 계단의 점수)
2. 2번에서 실수를 안하기 위해서, 2번의 조건에 유의하여야한다.
-> dp[n] = dp[n-1] + score_arr[n] 으로 하면 테스트케이스 오답이 나온다. (처음에 이렇게함..)
-> 바로 전단계를 밟고 N(끝 계단)을 밟으려면 전전단계를 밟으면 안된다.
-> 따라서, dp[n]= dp[n-3] + score_arr[n-1]+score_arr[n] (전전전 상태 누적 합 + 2단점프 계단(전 계단) + 끝 계단)
<개인 풀이>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#include<stdio.h>
#include<algorithm>
int score_arr[300]; //입력 받을 계단 점수
int dp[300]; //계단 최대의 값 300층 -> max(조건1,조건2)의 dp[299]
using namespace std;
int get_max(int a, int b)
{
if (a > b) return a;
else if (a < b) return b;
}
int main(void)
{
int n = 0;
int score = 0;
scanf("%d", &n);
for (unsigned short i = 0; i < n; ++i)
{
scanf("%d", &score);
score_arr[i] = score;
}
/* 처음 계단, 위치 경우의수 초기화*/
dp[0] = score_arr[0];
dp[1] = get_max((score_arr[0] + score_arr[1]), score_arr[1] );
dp[2] = get_max((score_arr[0] + score_arr[2]), (score_arr[1] + score_arr[2]));
// 바로전 연속 1칸씩 3회이상 갈수없음
// n 이전 계단
// dp[n] = dp[n-3]+score_arr[n-1]+score_arr[n];
// n 이전전 계단
// dp[n] = dp[n-2]+score_arr[n];
for (unsigned short i = 3; i < n; ++i)
{
dp[i] = get_max((dp[i - 3] + score_arr[i - 1] + score_arr[i]), (dp[i - 2] + score_arr[i]));
}
printf("%d\n", dp[n - 1]);
return 0;
}
|
'Algorithm > 동적계획법(DP)' 카테고리의 다른 글
10844 쉬운 계단수 (0) | 2020.03.17 |
---|---|
11727 2 x n 타일링 2 (0) | 2020.03.17 |
1149 RGB거리 (0) | 2020.01.22 |
9095 1,2,3 더하기 (0) | 2020.01.20 |
11726 2xn타일링 (0) | 2020.01.20 |
댓글