문제 링크
https://www.acmicpc.net/problem/2688
문제 풀이
어떤 숫자가 줄어들지 않는다는 것은 그 숫자의 각 자리 수보다 그 왼쪽 자리 수가 작거나 같을 때라고 한다. 그렇다면 숫자를 구성할 때 특정 자리 k 이후의 숫자는 특정 자리 k의 수 이상을 만족하면 된다. 이때 숫자는 leading zero여도 만족하므로 0부터 9까지의 숫자 중에 줄어들지 않는 조건을 만족하는 순열을 구하면 되는 문제이다.
어떻게 되는지 확인해보자
1 자리 수일 때
1 자리 수인 경우 앞에 어떤 숫자도 올 수 없기 때문에 0,1,2,3,4,5,6,7,8,9 가 가능하며 10가지 수가 존재한다.
2 자리 수일 때
2 자리 수인 경우는 1 자리 수에서 확장해볼 수 있다.
- 첫 번째 자리 수가 0인 경우
- 두 번째 자리 수는 0~9까지 숫자가 가능하다.
- 첫 번째 자리 수가 1인 경우
- 두 번째 자리 수는 1~9까지 숫자가 가능하다.
- 첫 번째 자리 수가 2인 경우
- 두 번째 자리 수는 2~9까지 숫자가 가능하다.
- 첫 번째 자리 수가 3인 경우
- 두 번째 자리 수는 3~9까지 숫자가 가능하다.
이미 눈치채신 분들도 있겠지만 n번째 자리에 가능한 숫자의 갯수는 이전 자리 수부터 9까지 숫자가 올 수 있다는 것을 알 수 있다.
이전 값을 기반으로 같은 동작이 반복된다면 다이나믹 프로그래밍의 메모이제이션 기법으로 문제를 해결할 수 있다.
풀이 코드
파악한 규칙대로 작성한 코드
import java.util.Arrays;
import java.util.Scanner;
public class Main2 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int numberOfTestCases = scanner.nextInt();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numberOfTestCases; i++) {
int n = scanner.nextInt();
long[][] dp = new long[n + 1][10];
for (int j = 0; j < 10; j++) {
dp[1][j] = 1;
}
for (int j = 2; j <=n; j++) {
for (int k = 0; k < 10; k++) {
for (int l = k; l < 10; l++) {
dp[j][k] += dp[j-1][l];
}
}
}
long answer = Arrays.stream(dp[n]).sum();
sb.append(answer+"\\n");
}
System.out.println(sb);
scanner.close();
}
}
좀 더 dynamic programming 답게 수정한 코드
import java.util.Scanner;
public class Main3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int numberOfTestCases = scanner.nextInt();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numberOfTestCases; i++) {
int n = scanner.nextInt();
long[][] dp = new long[n + 1][11];
// 0의 자리일 때 초기화
for (int j = 0; j <= 10; j++) {
dp[0][j] = 1;
}
// 1부터 n번째 자리 수까지 경우의 수 누적
for (int j = 1; j <= n; j++) {
// j번째 자리 수일 때 숫자별로 가능한 경우의 수를 누적
for (int k = 1; k <= 10; k++) {
dp[j][k] = dp[j][k - 1] + dp[j - 1][k];
}
}
// 마지막 열에 j 번째 행의 값이 모두 누적되므로
// n번째 행의 10 번째 열의 값이 정답
sb.append(dp[n][10]).append("\\n");
}
System.out.println(sb);
scanner.close();
}
}
좀 더 dp답게 푼 코드가 근소하게 시간이 덜 걸리는 것을 볼 수 있다.
'코딩테스트 > boj' 카테고리의 다른 글
보물섬 - 백준 2589 (0) | 2024.05.22 |
---|---|
떡 먹는 호랑이 - 백준 2502 자바 (0) | 2024.05.22 |
별 찍기 11 - 2448 (0) | 2024.03.30 |
벽 부수고 이동하기 - 백준 2206 (0) | 2024.03.30 |
램프 - 백준 1034 (0) | 2024.03.07 |