본문 바로가기
스터디(beakjoon)

Kotiln] 백준 9084번 풀이

by 김마리님 2024. 4. 17.

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

 

9084번: 동전

우리나라 화폐단위, 특히 동전에는 1원, 5원, 10원, 50원, 100원, 500원이 있다. 이 동전들로는 정수의 금액을 만들 수 있으며 그 방법도 여러 가지가 있을 수 있다. 예를 들어, 30원을 만들기 위해서는

www.acmicpc.net

 

더보기

이 문제도 DP 문제이다..

 

이 문제를 동전을 몇 개를 쓰느냐의 문제이다. 즉, 경우의 수 문제이다.

간단하게, 1 2 5 세 개의 동전으로 10을 맞춘다 생각해보자.

 

1의 동전으로 10을 맞추는 법을 보자.

1은 1을 1개 넣는 법,, 즉 1가지. 2는 2개 넣는법,, 1가지. 3개는 3개 넣는법,, 1가지.. 이렇게 된다.

즉, 10 모두 한 가지 방법을 가진다.

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

 

다음 2의 동전으로 만들어보자. 근데 dp이므로 이전 테이블을 그대로 활용한다.

2의 경우 1의 동전을 2개 사용하는 케이스, 그리고 2의 동전 1개를 사용하는 케이스가 추가된다. 따라서 +1이 된다.

3의 경우, 1의 동전 3개과 1의 동전 1개, 2의 동전 1개를 맞춰서 만드는 케이스, 두 가지가 생긴다.

두번째 케이스를 보자. 즉, 2를 뺐을 때 1원이 남게 된다. 이 말인 즉슨 2원을 뺀 1원이 됐을 때 만들 수 있는 경우를 추가해서 더해준다. 

4의 경우를 보자. 1의 동전 4개일 때 /  2원 1개, 1원 2개 / 2원 2개의 3개의 케이스가 생긴다.

원래 표에 존재하던 1의 동전 4개일 때를 제외하고 2원 1개, 1원 2개 / 2원 2개를 보자.

2원을 빼고 생각해보면 1원 2개, 2원 1개가 된다. 이건 2의 경우의 수와 동일하다. 즉, 2일때의 경우의 수를 더해준다.

이를 이용해서 나머지 표를 채워보자.

1 2 3 4 5 6 7 8 9 10
1 1+1 1+1 1+1+1 1+1+1 1+1+1+1 1+1+1+1 1+1+1+1+1 1+1+1+1+1 1+1+1+1+1+1
1 2 3 4 5 6 7 8 9 10
1 2 2 3 3 4 4 5 5 6

 

마지막 5원 역시 5원을 최소로 넣을 수 있을 때가 5인데,

5의 경우 5원을 추가한 케이스 하나를 추가한다.

10원의 경우,  위와 동일한 방식으로 5원을 빼면 5를 만들때와 동일한 식을 가지게 될 것이므로 5일때의 경우의 수를 추가한다.

1 2 3 4 5 6 7 8 9 10
1 2 2 3 3+1 4 4 5 5 6+3+1
1 2 3 4 5 6 7 8 9 10
1 2 2 3 4 4 4 5 5 10

 

이를 점화식으로 정리해보면,

1. 첫 동전(2원을 넣을때는 2원일 경우, 5원을 넣을때는 5원의 경우)을 넣을 때는 그 동전을 넣으면 0이 되므로 1을 추가하는 것 말고는 경우의 수를 가지지 않으므로

dp[i]++

2. 이후에는 기존에 존재하던 경우에 더하여 동전을 빼고 난 후의 값의 경우의 수를 추가하므로 

dp[i] = dp[i] + dp[i-coin]

이 되겠다.

 

이를 코드로 적어보면

fun main(args: Array<String>) {
    question9084()
}

fun question9084() {
    val case = readln().toInt()

    for (i in 1..case) {
        val kindCount = readln().toInt()
        val kind = readln().split(" ").map { it.toInt() }
        val bill = readln().toInt()

        val dp = Array(bill + 1) { 0 }

		// 동전의 종류대로 넣어봄
        for (j in 0..<kindCount) {

            for (k in 1..bill) {
            	// 동전이 가격보다 커지면 동전을 뺄 수 있다.
                if(k - kind[j] > 0) {
                    dp[k] = dp[k] + dp[k - kind[j]]
                    // 동전이 가격과 같으면 +1 해줌 
                    // 어차피 동전 하나 빼도 0이라 경우의 수가 없으므로 그냥 왕동전 하나 경우의 수 1추가 해주는거.
                } else if(k - kind[j] == 0){
                    dp[k]++
                }

                //println("dp[$k] = ${dp[k]}")

            }

        }

        println(dp[bill])

    }
}

 

((우우 dp 너무 못한다 어떡하지))

반응형

'스터디(beakjoon)' 카테고리의 다른 글

Kotlin] 백준 17425번 풀이  (0) 2024.04.22
Kotlin] 백준 4375번 풀이  (0) 2024.04.18
Kotlin] 백준 14501번 문제풀이  (0) 2024.04.12
Kotlin] 백준 1463번 문제풀이  (0) 2024.04.09
Kotlin] 백준 1655번 문제 풀이  (0) 2024.04.08