728x90

문제

오른쪽 그림과 같이 삼각형이 나선 모양으로 놓여져 있다. 첫 삼각형은 정삼각형으로 변의 길이는 1이다. 그 다음에는 다음과 같은 과정으로 정삼각형을 계속 추가한다. 나선에서 가장 긴 변의 길이를 k라 했을 때, 그 변에 길이가 k인 정삼각형을 추가한다.

파도반 수열 P(N)은 나선에 있는 정삼각형의 변의 길이이다. P(1)부터 P(10)까지 첫 10개 숫자는 1, 1, 1, 2, 2, 3, 4, 5, 7, 9이다.

N이 주어졌을 때, P(N)을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다. (1 ≤ N ≤ 100)

 

출력

각 테스트 케이스마다 P(N)을 출력한다.

 

예제 입력 1

2
6
12

 

예제 출력 1

3
16

 

출처

ICPC > Regionals > Asia Pacific > Korea > Asia Regional - Daejeon 2013 G번

 

알고리즘 분류

  • 수학
  • 다이나믹 프로그래밍

 

문제 출처

https://www.acmicpc.net/problem/9461

 

9461번: 파도반 수열

오른쪽 그림과 같이 삼각형이 나선 모양으로 놓여져 있다. 첫 삼각형은 정삼각형으로 변의 길이는 1이다. 그 다음에는 다음과 같은 과정으로 정삼각형을 계속 추가한다. 나선에서 가장 긴 변의

www.acmicpc.net

 


문제 해결 방법

점화식 구하기

  • 문제에서 주어진 그림을 통해 도출되는 값을 분석하면 다음과 같다.
N 출력값(P(N))
1 1
2 1
3 1
4 2
5 2
6 P(5) + P(1) = 3
7 P(6) + P(2) = 4
8 P(7) + P(3) = 5
9 P(8) + P(4) = 7
10 P(9) + P(5) = 9
  • $N ≥ 6$ 일 경우, 다음과 같이 점화식을 구할 수 있다.
$$P(N) = P(N - 1) + P(N - 5)$$

 

점화식을 토대로 구현하기

  • $N \ge 6$ 부터 점화식이 성립하므로, DP 테이블에서 $1 \le N < 6$ 범위는 문제에서 주어진 수(@1@, @1@, @1@, @2@, @2@)로 채운다.
// P(N) = P(N - 1) + P(N - 5) (N >= 6)
ULL Calc(int n) {
    dp[1] = dp[2] = dp[3] = 1;
    dp[4] = dp[5] = 2;

    for (int i = 6; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 5];
    }

    return dp[n];
}

 

  • @N = 100@ 일 경우, @888855064897@ 의 큰 수가 출력된다. 따라서 DP 테이블의 자료형을 @unsigned long long@ 으로 선언하하여 DP 테이블에 큰 수가 담길 수 있도록 하였다.
using ULL = unsigned long long;
vector<ULL> dp;

void Input() {
    cin >> N;
    dp.resize(N + 1);
}

 

 정확하게 풀기
  • 파도반 수열의 정확한 점화식은 $P(1) = P(2) = P(3) = 1, \quad P(N) = P(N - 1) + P(N - 2) \; (N \ge 4)$ 이다.
  • 이 점화식을 토대로 코드를 작성하면 다음과 같다.
// P(1) = P(2) = P(3) = 1 (N < 4)
// P(N) = P(N - 2) + P(N - 3) (N >= 4)
ULL Calc(int n) {
    dp[1] = dp[2] = dp[3] = 1;

    for (int i = 4; i <= n; i++) {
        dp[i] = dp[i - 2] + dp[i - 3];
    }

    return dp[n];
}

 

코드

#include <iostream>
#include <vector>
using namespace std;

using ULL = unsigned long long;

int T, N;
vector<ULL> dp;

void Input() {
    cin >> N;
    dp.resize(N + 1);
}

// P(N) = P(N - 1) + P(N - 5) (N >= 6)
ULL Calc(int n) {
    dp[1] = dp[2] = dp[3] = 1;
    dp[4] = dp[5] = 2;

    for (int i = 6; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 5];
    }

    return dp[n];
}

void Output() {
    cout << Calc(N) << '\n';
    dp.empty();
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    cin >> T;
    for (int i = 0; i < T; i++) {
        Input();
        Output();
    }    

    return 0;
}

 

채점 결과

 

참고

  • [단계별로 풀어보기] > [동적 계획법 1]
  • 실버III

 

파도반 수열(Padovan Sequence)

Padovan Sequence

점화식($P(n)$)

  • $n \le 2$ 의 경우 점화식은 다음과 같다.
$$P(0)=P(1)=P(2)=1$$

 

  • $n > 3$ 의 경우 점화식은 다음과 같다.
$$P(n)=P(n-2)+P(n-3)$$

 

참고 사이트

 

Padovan sequence - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Sequence of integers In number theory, the Padovan sequence is the sequence of integers P(n) defined[1] by the initial values P ( 0 ) = P ( 1 ) = P ( 2 ) = 1 , {\displaystyle P(0)=P(1)

en.wikipedia.org

 

728x90

'Problem Solving > BOJ' 카테고리의 다른 글

[BOJ-1932][C++] 정수 삼각형  (0) 2022.12.08
[BOJ-1149][C++] RGB거리  (0) 2022.12.08
[BOJ-11652][C++] 카드  (0) 2022.12.07
[BOJ-1912][C++] 연속합  (0) 2022.12.07
[BOJ-1904][C++] 01타일  (0) 2022.12.07
[BOJ-9184][C++] 신나는 함수 실행  (0) 2022.12.04
[BOJ-24416][C++] 알고리즘 수업 - 피보나치 수 1  (0) 2022.12.01
[BOJ-14889][C++] 스타트와 링크  (0) 2022.12.01