[코딩테스트] 🔥 마법 상어의 파이어볼 - 백준 20056

2025. 9. 30. 14:30알고리즘

문제링크

문제링크

난이도

골드 4

유형

구현

소요시간

1시간 반

회고

문제 이해하는데 시간이 오래걸렸다. 손코딩으로 문제 돌려보는데 예상 결과와 달라서 질문 게시판을 통해서 문제를 제대로 이해할 수 있었다.

이제 무한 이동과 간단한 좌표 이동 문제는 익숙해진 거 같다

코드

    typealias F = (m: Int, s: Int, d: Int)
    typealias FList = [F]

    let nmk = readLine()!.split(separator: " ").map { Int($0)! }
    let (N, M, K) = (nmk[0], nmk[1], nmk[2])

    var arr: [[FList]] = Array(repeating: Array(repeating: [], count: N), count: N)

    (0..<M).forEach { i in
        let row = readLine()!.split(separator: " ").map { Int($0)! }
        let (r, c, m) = (row[0], row[1], row[2])
        let (s, d) = (row[3], row[4])
        arr[r - 1][c - 1].append((m, s, d))
    }


    // move
    (0..<K).forEach { _ in

        var next: [[FList]] = Array(repeating: Array(repeating: [], count: N), count: N)
        // search
        (0..<N).forEach { r in
            (0..<N).forEach { c in
                arr[r][c].forEach { f in
                    let (nr, nc) = move(f, r: r, c: c)
                    next[nr][nc].append(f)
                }
            }
        }

        (0..<N).forEach { r in
            (0..<N).forEach { c in
                if next[r][c].count < 2 { return }

                let flist = next[r][c]

                let m = flist.map(\.m).reduce(0, +) / 5

                guard m != .zero else {
                    next[r][c] = []
                    return
                }
                let s = flist.map(\.s).reduce(0, +) / flist.count

                let isEven = flist.allSatisfy { $0.d.isMultiple(of: 2) }
                let isOdd = flist.allSatisfy { $0.d.isMultiple(of: 2) == false }
                let d =  isOdd || isEven ? [0, 2, 4, 6] : [1, 3, 5, 7]

                next[r][c] = d.map { F(m: m, s: s, d: $0) }
            }
        }

        arr = next
    }

    func move(_ f: F, r: Int, c: Int) -> (r: Int, c: Int) {
        let dr = [-1, -1, 0, 1, 1, 1, 0, -1]
        let dc = [0, 1, 1, 1, 0, -1, -1, -1]

        let d = f.d
        let r = infinite(n: r + dr[d] * (f.s % N), len: N)
        let c = infinite(n: c + dc[d] * (f.s % N), len: N)
        return (r, c)
    }

    func infinite(n: Int, len: Int) -> Int {
        ((n % len) + len) % len
    }

    var answer = 0
    (0..<N).forEach { r in
        (0..<N).forEach { c in
            answer += arr[r][c].map(\.m).reduce(0, +)
        }
    }

    print(answer)
    //    func debug() {
    //        (0..<N).forEach { r in
    //            (0..<N).forEach { c in
    //                print(arr[r][c].map(\.m), terminator: "\t")
    //            }
    //            print()
    //        }
    //    }
    //
    //    debug()