Uknow's Lab.
article thumbnail

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

 

17281번: ⚾

⚾는 9명으로 이루어진 두 팀이 공격과 수비를 번갈아 하는 게임이다. 하나의 이닝은 공격과 수비로 이루어져 있고, 총 N이닝 동안 게임을 진행해야 한다. 한 이닝에 3아웃이 발생하면 이닝이 종

www.acmicpc.net

 

난이도 : 골드 4
태그 : 구현, 브루트포스

 

 

설명

어려웠습니다. 정말 어려웠습니다.

소스코드 구현은 그렇게까지 어렵진 않았습니다. 그냥 백트래킹을 사용한 순열 구하기 + 게임 시뮬레이션 구현 이였기에.

다만... 문제를 이해하는데만 30분~1시간 정도가 걸린 것 같습니다

 

먼저, 타자의 순서를 정하고, (4번째 타자는 1번 선수로 고정)

모든 조합에 대해 게임 시뮬레이션을 진행하면 됩니다.

 

각 이닝은 아웃이 세 번 되면 끝나며, 다음 이닝으로 넘어가는데,

다음 이닝으로 넘어가더라도 타자의 순서는 그대로이며,

다음에 쳐야하는 타자 역시 그대로 입니다. (직전 이닝에서 4번 타자가 쳤다면, 이번 이닝에서는 5번 타자가 쳐야함)

 

 

소스코드

import java.util.*
import kotlin.math.max

lateinit var player: Array<Array<Int>>
val nowPlayer = Array(10) { 0 }
var n = 0
var maxScore = 0
lateinit var visited: Array<Boolean>

fun main() = with(System.`in`.bufferedReader()) {
    n = readLine().toInt()
    visited = Array(10) { false }

    player = Array(n) {
        val st = StringTokenizer(readLine())
        Array(10) { if (it == 0) 0 else st.nextToken().toInt() }
    }

    // 1번 선수가 4번 타자
    visited[1] = true
    nowPlayer[4] = 1
    getArray(1)

    println(maxScore)
}


// 순열
fun getArray(depth: Int) {
    when (depth) {
        10 -> gamePlay()
        4 -> getArray(depth + 1)
        else -> {
            for (i in 1..9) {
                if (!visited[i]) {
                    visited[i] = true
                    nowPlayer[depth] = i
                    getArray(depth + 1)
                    visited[i] = false
                }
            }
        }
    }
}


fun gamePlay() {
    var score = 0
    var playerIdx = 0

    for (inning in 0 until n) {
        var outCnt = 0
        val base = Array(3) { false } // 1루 2루 3루

        while (true) {
            if (++playerIdx > 9) playerIdx = 1

            when (player[inning][nowPlayer[playerIdx]]) {
                // 0 - 아웃, 1 - 1칸씩 진루, 2 - 2칸씩 진루, 3 - 3칸씩 진루, 4 - 홈런,
                0 -> if (++outCnt >= 3) break
                1 -> {
                    // 모든 타수는 1칸씩 진루
                    if (base[2]) score++
                    base[2] = base[1]
                    base[1] = base[0]
                    base[0] = true
                }

                2 -> {
                    if (base[2]) score++
                    if (base[1]) score++
                    base[2] = base[0]
                    base[1] = true
                    base[0] = false
                }

                3 -> {
                    score += base.count { it }
                    // 3진루 시 항상 3루는 차있고, 1, 2루는 비어있음
                    base[2] = true
                    base[1] = false
                    base[0] = false
                }

                4 -> {
                    score += base.count { it } + 1
                    // 홈런 시 모든 베이스는 비어있음
                    base.fill(false)
                }
            }
        }
    }

    maxScore = max(maxScore, score)
}

 

 

후기

구현 자체는 그리 어렵진 않았지만 지문을 이해하는데 꽤 걸렸던 문제였습니다.

profile

Uknow's Lab.

@유노 Uknow

인생은 Byte와 Double 사이 Char다. 아무말이나 해봤습니다.