[백준] 방 번호 (1082)(Kotlin)
문제 설명
이번에 VIP 회장으로 새로 부임한 백은진은 빅뱅의 위대함을 세계에 널리 알리기 위해서 사무실을 하나 임대했다.
빅뱅은 위대하기 때문에, 사무실의 번호도 되도록이면 커야 한다고 생각한다. 따라서 지금 가지고 있는 돈 전부를 가지고 방 번호를 만들려고 한다.
1층에 있는 문방구에서는 숫자를 판다. 각 숫자의 가격은 서로 다를 수 있기 때문에, 현재 가지고 있는 돈을 이용해서 만들 수 있는 가장 큰 숫자를 만들려고 한다.
예를 들어, 문방구에서 파는 숫자가 0, 1, 2이고, 각 숫자의 가격이 6, 7, 8이고, 백은진이 현재 가지고 있는 돈이 21이라면, 백은진이 만들 수 있는 가장 큰 수는 210(8+7+6=21)이다.
입력
문방구에서 파는 숫자의 개수 N이 주어진다. N은 10보다 작거나 같은 자연수이다. 문방구에서 파는 숫자는 0보다 크거나 같고, N-1보다 작거나 같은 자연수이다. 예를 들어, N=4이면, 문방구에서 파는 숫자는 0,1,2,3인 것이다. 둘째 줄에 각 숫자를 사는데 드는 비용이 작은 숫자부터 주어진다. 이 비용은 50보다 작거나 같은 자연수이다. 마지막 줄에는 백은진이 현재 가지고 있는 돈이 주어진다. 돈은 50보다 작거나 같은 자연수이다.
출력
첫째 줄에 백은진이 가지고 있는 돈으로 만들 수 있는 가장 큰 수를 출력한다. 백은진이 가지고 있는 돈은 적어도 숫자 하나는 살 수 있기 때문에, 답은 항상 존재한다.
0을 제외하고 0으로 시작하는 수는 없다.
테스트 케이스
입력 | 출력 |
---|---|
3 6 7 8 21 |
210 |
3 5 23 24 30 |
20 |
10 1 1 1 1 1 1 1 1 1 1 50 |
99999999999999999999999999999999999999999999999999 |
2 1 50 50 |
1 |
2 2 1 10 |
1111111111 |
1 10 20 |
0 |
3 6 7 8 6 |
0 |
문제 풀이1 (DFS - 실패)
import java.util.*
var N = 0
var costs = intArrayOf()
var maxLength = 0
val result = mutableSetOf<String>()
fun main() = with(Scanner(System.`in`)) {
N = nextInt()
costs = IntArray(N) { nextInt() }
val asset = nextInt()
for (i in N - 1 downTo 1) {
dfs(i, asset - costs[i], i.toString())
}
println(result)
println(result.maxWith(::compare))
}
fun compare(o1: String, o2: String): Int {
return if (o1.length == o2.length) {
var result = 0
for (i in o1.indices) {
if (o1[i] != o2[i]) {
result = o1[i] - o2[i]
break
}
}
result
} else {
o1.length - o2.length
}
}
fun dfs(num: Int, asset: Int, roomNum: String) {
if (asset <= 0 && roomNum.length > maxLength) {
// println("result : ${roomNum}, result.length : ${roomNum.length}")
maxLength = roomNum.length
result.add(roomNum)
return
}
for (i in num downTo 0) {
val remainAsset = asset - costs[i]
if (remainAsset >= 0) {
dfs(i, remainAsset, roomNum + i.toString())
} else {
dfs(i - 1, remainAsset, roomNum)
}
}
}
문제 풀이2 (DP - knapsack)
iimport java.util.Scanner
var N = 0
var costs = arrayOf<Pair<Int, Int>>()
val list = mutableListOf<Pair<String, Int>>()
fun main() = with(Scanner(System.`in`)) {
N = nextInt()
costs = Array(N) { Pair(it, nextInt()) }.sortedBy { it.second }.toTypedArray()
val start = costs.filter { it.first != 0 }.sortedBy { it.second }.toTypedArray()
val asset = nextInt()
for ((num, value) in start) {
if (asset - value >= 0) list.add(findMaxLengthNum(asset - value, num.toString()))
}
if (list.isEmpty()) {
println(0)
return
}
val maxLengthNum = list.maxWith(Comparator { o1, o2 ->
if (o1.first.length == o2.first.length) {
var result = 0
for (i in o1.first.indices) {
if (o1.first[i] != o2.first[i]) {
result = o1.first[i] - o2.first[i]
break
}
}
result
} else {
o1.first.length - o2.first.length
}
})!!
val result = maxLengthNum.first[0] + findMax(maxLengthNum.first.length, 1, maxLengthNum.first, maxLengthNum.second)
println(result)
}
fun findMax(depth: Int, index: Int, roomNum: String, asset: Int): String {
if (depth == index) return ""
var indexedNum = roomNum[index]
var indexedNumCost = costs.find { it.first == roomNum[index].toInt() - 48 }!!.second
var remainedAsset = asset
for ((num, value) in costs) {
if (asset + indexedNumCost - value >= 0 && indexedNum.toInt() - 48 < num) {
indexedNum = num.toString()[0]
remainedAsset = asset + indexedNumCost - value
}
}
return indexedNum + findMax(depth, index + 1, roomNum, remainedAsset)
}
fun findMaxLengthNum(asset: Int, startNum: String): Pair<String, Int> {
var remainedAsset = asset
var maxLengthNum = startNum
for ((num, value) in costs) {
if (remainedAsset - value >= 0) {
val quotient = asset / value
remainedAsset -= (value * quotient)
repeat (quotient) {
maxLengthNum += num
}
}
}
return Pair(maxLengthNum, remainedAsset)
}