Skip to content

Commit

Permalink
day5: (2) dp/10844, dp/11057
Browse files Browse the repository at this point in the history
  • Loading branch information
CheolHoJung committed Mar 28, 2019
1 parent 7c35de5 commit 817a24f
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 0 deletions.
84 changes: 84 additions & 0 deletions dp/쉬운_계단_수.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package test.boj.dp;

import org.junit.*;

import java.io.*;

import static org.assertj.core.api.Assertions.assertThat;

public class 쉬운_계단_수 {

public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write(solution(Integer.parseInt(br.readLine())) + "\n");
bw.flush();
bw.close();
br.close();
}

@Test
public void test() {
assertThat(solution(1))
.isEqualTo(9);
assertThat(solution(2))
.isEqualTo(17);
assertThat(solution(3))
.isEqualTo(32);
assertThat(solution(100))
.isEqualTo(18404112);
}

// 1 -> 10, 12 -> 101, 121, 123
// 2 -> 21, 23 -> 210, 212, 232, 234
// 3 -> 32, 34 -> 321, 324, 343, 346
// 4 -> 43, 45 -> 432, 434, 454, 456
// 5 -> 54, 56 -> 543, 545, 565, 567
// 6 -> 65, 67 -> 654, 656, 676, 678
// 7 -> 76, 78 -> 765, 767, 787, 789
// 8 -> 87, 89 -> 876, 878, 898
// 9 -> 98 -> 987, 989
// 1. 끝자리에 +- 1수를 추가 -> dp[N][L] = dp[N - 1][L - 1] + dp[N - 1][L + 1]
// 2. 끝자리가 0인 경우 +1만 추가 -> dp[N][L] = dp[N - 1][L + 1]
// 3. 끝 자리가 9인 경우 -1만 추가 -> dp[N][L] = dp[N - 1][L - 1]
public static int solution(int N) {
// 1~100 = 100 + 1 = 101 (0 예외), 1~9 = 9 + 2 = 11(0, 10 예외)
// dp[N][L] = 길이 N, 마지막 숫자가 L인 경우의 수
long[][] dp = new long[101][11];

for (int i = 1; i <= 9; i++) {
dp[1][i] = 1;
}

for (int i = 2; i <= N; i++) {
// 점화식1
dp[i][0] = dp[i - 1][1];
for (int j = 1; j <= 9; j++) {
// 점화식 1, 3
// 점화식 3. dp[N][L] = dp[N - 1][L - 1]을 따로 처리하지 않는
// 이유는 dp[i][10]의 값은 항상 0이라 굳이 처리할 필요가 없음
dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % 1_000_000_000;
}
}

long sum = 0;
for (int i = 0; i <= 9; i++) {
sum += dp[N][i];
}

return (int) (sum % 1_000_000_000);
}

// 오답, n = 3까지만 맞음
private static int failSolution(int N) {
long[] dp = new long[101];
dp[1] = 9;

for (int i = 2; i <= N; i++) {
dp[i] = ((dp[i - 1] * 2) - (i - 1)) % 1_000_000_000;
System.out.println(dp[i]);
}

return (int) dp[N];
}
}
147 changes: 147 additions & 0 deletions dp/오르막_수.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package test.boj.dp;

import org.junit.*;

import java.io.*;

import static org.assertj.core.api.Assertions.assertThat;

public class 오르막_수 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

bw.write(solution(Integer.parseInt(br.readLine())) + "\n");
bw.flush();
bw.close();
br.close();
}

@Test
public void test() {
assertThat(solution(1))
.isEqualTo(10);
assertThat(solution(2))
.isEqualTo(55);
assertThat(solution(3))
.isEqualTo(220);
}

// N = 1
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
//
// N = 2 -> 55개
// 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 - 10개 -> N = 3: sum(1..10) - 55
// 11, 12, 13, 14, 15, 16, 17, 18, 19 - 9개 -> N = 3: sum(1..9) - 45
// 22, 23, 24, 25, 26, 27, 28, 29 - 8개 -> N = 3: sum(1..8) - 36
// 33, 34, 35, 36, 37, 38, 39 - 7개 -> N = 3: 28
// 44, 45, 46, 47, 48, 49 - 6개 -> N = 3: 21
// 55, 56, 57, 58, 59 - 5개 -> N = 3: 15
// 66, 67, 68, 69 - 4개 -> N = 3: 10
// 77, 78, 79 - 3개 -> N = 3: 6
// 88, 89 - 2개 -> N = 3: 3
// 99 - 1개 -> N = 3: sum(1..1) 1
//
// N = 3, 첫번 째 00 ~ 09에서만 55개 sum(sum(1..1) +....+ sum(1..10))
// 000, 001, 002, 003, 004, 005, 006, 007, 008, 009
// 011, 012, 013, 014, 015, 016, 017, 018, 019
// 022, 023, 024, 025, 026, 027, 028, 029
// 033, 034, 035, 036, 037, 038, 039
// 044, 045, 046, 047, 048, 049
// 055, 056, 057, 058, 059
// 066, 067, 068, 069
// 077, 078, 079
// 088, 089
// 099
// N = 1 -> dp[N][L] = 1
// N > 1 -> dp[N][L] = dp[N - 1][L] + dp[N - 1][L + 1] + ...... L <= 9
private static int solution(int n) {
long[][] dp = new long[1001][10];
for (int i = 0; i < 10; i++) {
dp[1][i] = 1;
}

for (int N = 2; N <= n; N++) {
dp[N][9] = 1;
for (int L = 0; L <= 9; L++) {
for (int M = L; M <= 9; M++) {
dp[N][L] += dp[N - 1][M];
}
dp[N][L] %= 10_007;
}
}

int sum = 0;
for (int i = 0; i < 10; i++) {
sum += dp[n][i];
}
return sum % 10_007;
}

@Test
public void test2() {
assertThat(solution2(1))
.isEqualTo(10);
assertThat(solution2(2))
.isEqualTo(55);
assertThat(solution2(3))
.isEqualTo(220);
}

// dp[N][L + 1]은 dp[N][L]에서 맨 윗 계단(9개)을 떼어낸 것으로 볼 수 있다.
// N = 4, L = 1
// 111, 112, 113, 114, 115, 116, 117, 118, 119 <- dp[4][2]는 이 부분을 떼어낸 모습(9개)
// 122, 123, 124, 125, 126, 127, 128, 129
// 133, 134, 135, 136, 137, 138, 139
// 144, 145, 146, 147, 148, 149
// 155, 156, 157, 158, 159
// 166, 167, 168, 169
// 177, 178, 179
// 188, 189
// 199
// N = 4, L = 2
// 222, 223, 224, 225, 226, 227, 228, 229
// 233, 234, 235, 236, 237, 238, 239
// 244, 245, 246, 247, 248, 249
// 255, 256, 257, 258, 259
// 266, 267, 268, 269
// 277, 278, 279
// 288, 289
// 299

// 떼어진 맨 윗 계단은 dp[N - 1][L]와 같은 모양이므로 해당 계단을 떼어서 맨 위로 붙이면 dp[N][L]이 완성된다.
// N = 3, L = 1
// 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 (9개)
// N = 1 -> dp[N][L] = 1
// N > 1 && L == 9 -> dp[N][L] = 1
// && L <= 8 -> dp[N][L] = dp[N][L + 1] + dp[N - 1][L]
private static int solution2(int n) {
long[][] dp = new long[1001][10];
for (int i = 0; i < 10; i++) {
dp[1][i] = 1;
}

for (int N = 2; N <= n; N++) {
dp[N][9] = 1;
for (int L = 8; L >= 0; L--) {
dp[N][L] = dp[N - 1][L] + dp[N][L + 1];
dp[N][L] %= 10007;
}
}

int sum = 0;
for (int i = 0; i < 10; i++) {
sum += dp[n][i];
}
return sum % 10_007;
}
}

0 comments on commit 817a24f

Please sign in to comment.