본문 바로가기
  • 개발하는 곰돌이
Algorithm/BOJ

[Kotlin] 백준 27162 : Yacht Dice

by 개발하는 곰돌이 2023. 9. 5.

문제 링크

 

27162번: Yacht Dice

《Yacht Dice》는 여러 명이 플레이하는 주사위 게임입니다. 플레이어는 우선 주사위를 $5$개 굴립니다. 이후 원하는 주사위를 고정시킨 뒤, 남은 주사위를 다시 굴리는 일을 두 번 이하로 할 수 있

www.acmicpc.net


문제 해설

다양한 조건 분기에 따라 조건에 맞는 계산을 수행하는 문제. Y에 해당하는 족보의 점수를 모두 계산한 후 가장 높은 값을 출력하면 된다.

 

이미 3개의 주사위가 고정되어 있기 때문에 나머지 2개의 주사위가 최적인 경우를 생각해볼 수 있다.

  • Ones부터 Sixes까지는 나머지 2개의 주사위가 족보에서 요구하는 주사위의 눈이 나왔을 때 최대가 된다. 즉, 입력으로 주어진 고정된 주사위 중에서 (족보에 따라 1~6의 개수 + 2)\(\times\)족보에 따른 수만큼 점수를 얻는다.
    • 예를 들어 Ones일 경우 (입력 중 1의 개수 + 2)\(\times\)1이 되고, Fives일 경우 (입력 중 5의 개수 + 2)\(\times\)5가 된다.
  • Four of a Kind는 나머지 2개의 주사위까지 합쳐서 같은 눈의 주사위가 4개 이상이면 된다. 즉, 고정된 주사위 중 같은 눈의 개수가 2개 이상인 수\(\times\)4가 되고, 없는 경우에는 0이 된다.
  • Full House부터는 고정된 주사위에서 중복을 제거한 경우를 기준으로 판단한다.
    • 중복을 제거한 주사위의 개수가 1개인 경우(3개의 주사위가 모두 같은 눈인 경우)에는 주사위의 눈이 6일때와 6이 아닐 때로 나눌 수 있다.
      • 3개의 주사위가 모두 6인 경우에는 6\(\times\)3 + 5\(\times\)2 = 28이 최대가 된다.
      • 그 외의 경우에는 (고정된 주사위의 눈)\(\times\)3 + 6\(\times\)2가 최대가 된다.
    • 중복을 제거한 주사위의 개수가 2개인 경우(2개의 주사위가 같은 눈이고 1개의 주사위가 다른 경우)에는 (둘 중 큰 수)\(\times\)3 + (둘 중 작은 수)\(\times\)2가 최대가 된다. 큰 수가 2번 나왔을 때는 나머지 주사위에서 큰 수 1번, 작은 수 1번만 나오면 되고, 큰 수가 1번만 나왔을 때는 나머지 주사위에서 큰 수 2번이 나오면 되기 때문이다.
    • 중복을 제거한 주사위의 개수가 3개인 경우(3개의 주사위가 모두 다른 경우)에는 Full House가 불가능하기 때문에 0점이 된다.
  • Little Straight는 중복을 제거한 주사위의 개수가 3개이면서 6을 포함하지 않고 있을 때 30점, 그 외의 경우엔 0점이 된다. 중복된 수가 하나라도 존재하거나 6을 포함하고 있다면 5개를 뽑았을 때 1 2 3 4 5를 뽑을 수 없기 때문이다.
  • Big Straight는 마찬가지로 중복을 제거한 주사위의 개수가 3개이면서 1을 포함하지 않고 있을 때 30점, 그 외의 경우엔 0점이 된다.
  • Yacht는 중복을 제거한 주사위의 개수가 1개(3개의 주사위가 모두 같은 경우)일 때 50점, 그 외엔 0점이 된다.
  • Choice는 그냥 주사위의 눈의 합계 + 12를 하면 최대가 된다.

이렇게 계산한 점수 중 최대값이 정답이 된다.

Code

import java.util.StringTokenizer

fun main() = with(System.`in`.bufferedReader()) {
    val pedigree = readLine()
    val dice = StringTokenizer(readLine()).run { IntArray(3) { nextToken().toInt() } }
    val distinctDice = dice.distinct().toIntArray()
    val scores = IntArray(12)
    for (i in scores.indices) {
        if (pedigree[i] == 'N') continue
        scores[i] = when (i) {
            0 -> dice.homework(1)
            1 -> dice.homework(2)
            2 -> dice.homework(3)
            3 -> dice.homework(4)
            4 -> dice.homework(5)
            5 -> dice.homework(6)
            6 -> dice.calcFourOfAKind()
            7 -> distinctDice.calcFullHouse()
            8 -> distinctDice.calcLittleStraight()
            9 -> distinctDice.calcBigStraight()
            10 -> distinctDice.calcYacht()
            else -> dice.sum() + 12
        }
    }
    println(scores.max())
}

private fun IntArray.homework(n: Int) = (2 + count { it == n }) * n
private fun IntArray.calcFourOfAKind() = filter { n -> count { it == n } >= 2 }.run { if (isNotEmpty()) get(0) * 4 else 0 }
private fun IntArray.calcFullHouse() = if (size == 1) if (sum() == 6) 28 else 12 + sum() * 3 else if (size == 2) max() * 3 + min() * 2 else 0
private fun IntArray.calcLittleStraight() = if (size == 3 && !contains(6)) 30 else 0
private fun IntArray.calcBigStraight() = if (size == 3 && !contains(1)) 30 else 0
private fun IntArray.calcYacht() = if (size == 1) 50 else 0

댓글