문제

0부터 N까지의 정수 K개를 더해서 그 합이 N이 되는 경우의 수를 구하는 프로그램을 작성하시오.

덧셈의 순서가 바뀐 경우는 다른 경우로 센다(1+2와 2+1은 서로 다른 경우). 또한 한 개의 수를 여러 번 쓸 수도 있다.

입력

첫째 줄에 두 정수 N(1 ≤ N ≤ 200), K(1 ≤ K ≤ 200)가 주어진다.

출력

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

내가 푼 풀이

- N이 주어졌을때, 0부터 N까지 k번을 더해서 N을 만드는 경우의 수를 구한다.

- K = 1 인경우, 한번만 더해서 N을 만드려면 N 자기 자신을 더하는 방법 1가지다.

- K = 2 인경우, 두번 더해서 N을 만드려면 , 0 + N , 1 + (N-1), ... , N + 0 으로 N가지이다.

- 이를 "dp[n][k] = 0부터N까지의 정수 K번 더해서 합이 N이되는 경우의수" 로 정의하자.

- K = 1 인경우 자기 자신만 더하면 되므로 dp[n][1] = 1

- K = 2 인경우 자기 자신을 1씩차감한만큼 더해주면 되므로, dp[n][2] = n 이된다.

- 이제 K = 3 부터는 이전의 값을 저장된 값을 사용하려한다.

- 3번 더해서 N을 만드는 경우의 수를 초기값이 0부터 N까지의 경우의수를 생각해보자.

예시로 N = 3 , K = 3 일때

  • 초기값 = 0 이라면, 나머지 3, 두번을 더해서 3을 만들때 => dp[3][2]
  • 초기값 = 1 이라면, 나머지 2, 두번을 더해서 3을만들때 => dp[2][2]
  • 초기값 = 2 이라면, 나머지 1, 두번을 더해서 3을 만들때 => dp[1][2]
  • 초기값 = 3 이라면 나머지 0, 두번을 더해서 3을 만들때 => dp[0][2]

로 나타낼 수 있다.

이는 dp[n][k] = k번 더해서 합이 n이되는 경우의 수 이기때문이다.

위를 바탕으로 N = 5, K = 3 일때의 dp를 구하면 다음과 같다.

DP 1 2 3
0 1 1 1
1 1 2 3
2 1 3 6
3 1 4 10
4 1 5 15
5 1 6 21

따라서 0부터5까지 정수를 3번 더해서 합이 5가되는 경우의 수는 21이 된다.dp[5][3]

 

이를 코드로 구현하면 다음과 같다.

 

import Foundation

var input = readLine()!.split(separator: " ").map{ Int($0)! }
var dp = Array(repeating: Array(repeating: 0, count: input[1]+1), count: input[0]+1)

// DP 입력
// dp[n][k] = dp[n][k] + dp[i][k-1] (i는 0부터 n까지의 정수)
for i in 1...input[1] {
    for j in 0...input[0] {
        if i == 1 || j == 0 {
            dp[j][i] = 1
            continue
        }
        for k in 0...j {
            dp[j][i] = (dp[j][i] + dp[k][i-1]) % 1000000000
        }
    }
}
print(dp[input[0]][input[1]])

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-11724 연결 요소의 개수 Swift  (0) 2023.05.31
BOJ-12904 A와B Swift  (0) 2023.05.31
BOJ-1697 숨바꼭질 Swift  (0) 2023.05.30
BOJ-7576 토마토 Swift  (0) 2023.05.30
BOJ-15903 카드 합체 놀이 Swift  (0) 2023.05.30

+ Recent posts