알고리즘

[백준] 계단 수 1562 - java

minkang 2021. 7. 7. 00:48

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

 

1562번: 계단 수

첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다.

www.acmicpc.net

public class 계단수 {
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
		int dp[][][] = new int[N + 1][10][1 << 10];
		int MOD = 1000000000;
		for (int i = 1; i <= 9; i++) {
			dp[1][i][1 << i] = 1;
		}

		for (int i = 2; i <= N; i++) {
			for (int j = 0; j <= 9; j++) {
				for (int k = 0; k < (1 << 10); k++) {
					if (j == 0) {
						dp[i][0][1 << 0 | k] = (dp[i][0][1 << 0 | k] + dp[i - 1][1][k]) % MOD;
					} else if (j == 9) {
						dp[i][9][1 << 9 | k] = (dp[i][9][1 << 9 | k] + dp[i - 1][8][k]) % MOD;
					} else {
						dp[i][j][1 << j | k] = (dp[i][j][1 << j | k] + dp[i - 1][j - 1][k] + dp[i - 1][j + 1][k]) % MOD;
					}
				}
			}
		}

		int answer = 0;
		for (int i = 0; i < 10; i++) {
			answer = (answer + dp[N][i][(1 << 10) - 1]) % MOD;
		}
		System.out.println(answer);
	}
}

DP와 비트마스킹을 활용한 문제입니다.

N이 주어질 때, 길이가 N이면서 0에서 9가 모두 등장하는 계단 수라는 조건이 없다는 가정하에

2차원 배열로 나타낸다면

int dp[][] = new int[N+1][10];

 

  0    1      2     3      4     5      6     7      8      9

1    0  2  1  3  2  4  3  5  4  6  5  7  6  8  7  9   8

 

- N이 1일 때

dp[1][1~9] = 1

 

- N은 2이고 일의 자릿수가 1일때

dp[2][1] = dp[1][0] + dp[1][2]

N은 2일때 일의 자리가 1의 갯수는 이전 길이의 0의 갯수와 2의 갯수를 더한 값입니다.

 

여기서 0에서 9가 모두 등장하는 계단 수라는 조건을 추가한다면

각 길이마다 선택된 자릿수와 그 갯수를 기록해야합니다.

따라서 3차원 배열로

int dp[][][] = new int[N+1][10][1<<10];  // 총 10개의 값을 구분해야하므로

 

- N은 1일 때

dp[1][1~9][1<<(1~9)] = 1;

 

- N은 2이고 일의 자릿수가 1일 때

이전에 선택된 자릿수와 현재 선택된 자릿수를 합하여 모든 상태를 구해야합니다.

for(int k=0; k< 1<<10; k++){

      dp[2][1][1<<1 | k] = dp[2][1][1<<1 | k] + dp[1][0][k] + dp[1][2][k];

}

현재 1을 선택했으므로 1 << 1 | k 입니다.

 

이런식으로 순회를 하면되는데 정답을 1,000,000,000으로 나눈 나머지를 출력한다라는 조건이 있어

각 자릿수를 구할때마다 나머지연산을 해야합니다.