https://www.acmicpc.net/problem/2688
2688번: 줄어들지 않아
문제 어떤 숫자가 줄어들지 않는다는 것은 그 숫자의 각 자리 수보다 그 왼쪽 자리 수가 작거나 같을 때 이다. 예를 들어, 1234는 줄어들지 않는다. 줄어들지 않는 4자리 수를 예를 들어 보면 0011, 1111, 1112, 1122, 2223이 있다. 줄어들지 않는 4자리수는 총 715개가 있다. 이 문제에서는 숫자의 앞에 0(leading zero)이 있어도 된다. 0000, 0001, 0002는 올바른 줄어들지 않는 4자리수이다. n이 주어졌을
www.acmicpc.net
2차원 DP를 사용하여 푼 문제였다. mat[i][j]를 이용하여 i개의 숫자가 주어질 때 j가 맨 앞자리라면 올 수 있는 수열의 갯수를 구하는 방법으로 풀었다. 규칙은 다음과 같다.
한자리
0 ~ 9 -> 10개
총 10개
두자리
00 ~ 09 -> 10개 (한자리 경우에서 0 ~ 9의 합)
11~19 -> 9개 (한자리 경우에서 1 ~ 9의 합)
22~29 -> 8개 (한자리 경우에서 2 ~ 9의 합)
.
.
.
88 ~ 89 : 2개 (한자리 경우에서 8~ 9의 합)
99 : 1개 (한자리 경우에서 9 ~ 9의 합)
총 55개
세자리
000 ~ 099 -> 55개 (두자리 경우에서 00 ~ 99의 합)
111 ~ 199 -> 45개 (두자리 경우에서 11 ~ 99의 합)
222 ~ 299 -> 36개 (두자리 경우에서 22 ~ 99의 합)
333 ~ 399 -> 28개 (두자리 경우에서 33 ~ 99의 합)
.
.
.
888 ~ 899 -> 3개 (두자리 경우에서 88 ~ 89의 합)
999 -> 1개 (두자리 경우에서 99 ~ 99의 합)
총 715개
규칙을 보면 mat[i][j]는 mat[i - 1][9] ~ mat[i - 1][j]의 합을 구한 결과이다. 또한 맨 앞자리가 9로 끝나면 경우의 수는 무조건 1개이다.
#include <iostream>
using namespace std;
long long int mat[65][10] = { 0, }; //64자리 모든 경우의 맨 앞의 올 수 있는 10가지의 숫자를 수열로 나열한 결과
long long int res[65]; //64자리 모두의 결과를 담을 공간
void func() {
for (int i = 0; i <= 64; i++) {
mat[i][9] = 1; //맨 앞자리가 9인 경우, 수열은 1가지만 존재한다.
}
for (int i = 1; i <= 64; i++) {
for (int j = 8; j >= 0; j--) { //큰 수에서 작은 수로 결과를 도출하였다.
mat[i][j] = mat[i - 1][j] + mat[i][j + 1]; //mat[i - 1][9] ~ mat[i - 1][j]까지의 합
}
}
for (int i = 0; i <= 64; i++) {
long long int sum = 0; //i자리일 때 결과의 합을 구할 변수
for (int j = 0; j <= 9; j++) {
sum = sum + mat[i][j]; //j가 맨 앞에 올 때의 가짓수를 더한다.
}
res[i] = sum; //i자리일 때 결과를 초기화
}
}
int main() {
int n, num;
func();
cin >> n;
for (int i = 0; i < n; i++) {
cin >> num;
cout << res[num] << '\n';
}
}
'백준' 카테고리의 다른 글
백준14500 - 테트로미노 (0) | 2020.02.17 |
---|---|
백준4485 - 녹색 옷 입은 애가 젤다지? (0) | 2020.02.15 |
백준2206 - 벽 부수고 이동하기 (0) | 2020.02.13 |
백준1261 - 알고스팟 (0) | 2020.02.12 |
백준3055 - 탈출 (0) | 2020.02.11 |