문제
정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 3가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다. 단, 같은 수를 두 번 이상 연속해서 사용하면 안 된다.
- 1+2+1
- 1+3
- 3+1
정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 100,000보다 작거나 같다.
출력
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.
예제 입력 1
3
4
7
10
예제 출력 1
3
9
27
다이나믹 프로그래밍 방식으로 경우의 수를 구하는 것은 많이 하였다. 이 번 문제는 여기에 연속하여 같은 수를 더해서는 안된다는 제한 조건이 붙었다. 다소 복잡해 보이지만, 제한 조건을 만족하는 지 확인하기 위해서는 그에 맞추어 나누어 저장할 필요가 있음을 생각해낼 수 있다면 충분히 풀 수 있다.
기본적인 골자는 n 을 만들어내는 합의 경우의 수를 n-1, n-2, n-3 의 경우의 수로 부터 이끌어내는 것은 같다. 다만 n 의 경우의 수를 마지막으로 1 을 더한 경우, 2 를 더한 경우, 3 을 더한 경우로 나누어 이중배열 형태로 저장할 것이다. 우리는 다음과 같은 결과를 이끌어 낼 수 있을 것이다.
자연수 i 의 합 조합에 대하여
cases[i][1] = cases[i-1][2] + cases[i-1][3]; //case[i-1][1]은 제외(중복 조건 위배)
cases[i][2] = cases[i-2][1] + cases[i-2][3]; //case[i-2][2]은 제외(중복 조건 위배)
cases[i][3] = cases[i-3][1] + cases[i-3][2]; //case[i-3][3]은 제외(중복 조건 위배)
나는 다음과 같이 문제를 풀었다.
- 테스트 개수와 입력 값들을 받는다.
- 입력값 중 가장 큰 값(max_num)을 구한다.
- 이중 배열 cases[n][4] 를 선언한다.
- cases[1][1], cases[2][2], cases[3][1], cases[3][2], cases[3][3]의 값을 미리 채워 놓는다.
- 4 인 경우부터 max_num인 경우 까지 이중 배열 cases를 채워 놓는다. 수가 커지는 관계로 미리 모듈러 연산을 하였다.
- 각각의 입력에 대해 1 을 마지막으로 더한 경우, 2 를 마지막으로 더한 경우, 3 을 마지막으로 더한 경우를 모두 더한 후 모듈러 연산을 해준 후 출력한다.
코드는 다음과 같다.
#include <iostream>
#include <algorithm>
#include <vector>
int cases[100001][4];
int main()
{
int N;
std::cin >> N;
std::vector<int> input;
cases[1][1] = 1;
cases[2][2] = 1;
cases[3][1] = 1;
cases[3][2] = 1;
cases[3][3] = 1;
for (int i = 0; i < N; i++)
{
int data;
std::cin >> data;
input.push_back(data);
}
int max_input = *std::max_element(input.begin(), input.end());
for (int i = 4; i <= max_input; i++)
{
cases[i][1] = (cases[i-1][2] + cases[i-1][3]) % 1000000009;
cases[i][2] = (cases[i-2][1] + cases[i-2][3]) % 1000000009;
cases[i][3] = (cases[i-3][1] + cases[i-3][2]) % 1000000009;
}
for (int i = 0; i < input.size(); i++)
{
std::cout <<
((long long)cases[input[i]][1] + cases[input[i]][2] + cases[input[i]][3]) % 1000000009
<< '\n';
}
return 0;
}
제한 조건을 어떻게 풀 것인가에 대해서 생각해 볼만한 문제였다. 이 것으로 글을 마친다.
'뭐라도 공부해보자!!( 이론 ) > 자료구조 및 알고리즘' 카테고리의 다른 글
백준 2193, 이친수 (0) | 2023.12.06 |
---|---|
백준 10844번, 쉬운 계단 수 (1) | 2023.12.04 |
백준 16194, 카드 구매하기 2 (1) | 2023.12.02 |
백준 11052, 카드 구매하기 (0) | 2023.12.02 |
백준 9095, 1, 2, 3 더하 (0) | 2023.11.30 |