Algorithm/Baekjoon

[λ°±μ€€] (Swift) 1107번 - 리λͺ¨μ»¨ (완전탐색, λ‘λ²ˆμ§Έ μ˜€λ‹΅λ…ΈνŠΈ)

감자 πŸ₯” 2022. 12. 30. 14:56
λ°˜μ‘ν˜•

🟠 문제

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

 

1107번: 리λͺ¨μ»¨

첫째 쀄에 μˆ˜λΉˆμ΄κ°€ μ΄λ™ν•˜λ €κ³  ν•˜λŠ” 채널 N (0 ≤ N ≤ 500,000)이 주어진닀.  λ‘˜μ§Έ μ€„μ—λŠ” κ³ μž₯λ‚œ λ²„νŠΌμ˜ 개수 M (0 ≤ M ≤ 10)이 주어진닀. κ³ μž₯λ‚œ λ²„νŠΌμ΄ μžˆλŠ” κ²½μš°μ—λŠ” μ…‹μ§Έ μ€„μ—λŠ” κ³ μž₯λ‚œ λ²„νŠΌ

www.acmicpc.net

 

🟠 λ‚˜μ˜ 풀이

λ¨Όμ € λ¬Έμ œκ°€,,, 일단 κ³¨λ“œλΌλŠ” 것에 덜μ»₯ 겁이 λ‚¬μ§€λ§Œ,, μ˜ˆμ „μ— ν•œλ²ˆ ν’€μ–΄λ΄€λ˜ λ¬Έμ œμ΄κΈ°μ— μ‘°κΈˆμ”© 기얡이 났닀. μ•Œκ³ λ¦¬μ¦˜ 문제 ν’€λ©΄μ„œ 이거 λ°±ν”„λ‘œ λ‹€μŒμ— κΈ°μ–΅λͺ»ν•¨ γ…‹γ…‹γ…‹ 이러고 ν’€μ§€λ§Œ, μ€κ·Όνžˆ 기얡이 λ‚œλ‹€! 

μš°μ„ , μœ„μ™€ 같은 κ²½μš°μ—λŠ” μ„Έκ°€μ§€μ˜ λ°©λ²•μœΌλ‘œ 채널을 이동할 수 μžˆλ‹€.

1. +, - λ²„νŠΌμœΌλ‘œλ§Œ μ™„λ²½ν•˜κ²Œ 이동
2. μˆ«μžλ²„νŠΌμ΄ κ³ μž₯λ‚˜μ§€ μ•Šμ•„μ„œ, μˆ«μžλ²„νŠΌμœΌλ‘œλ§Œ 이동
3. μˆ«μžλ²„νŠΌμ΄ κ³ μž₯λ‚œ 것이 μƒκ²¨μ„œ κ°€κΉŒμš΄ μ–΄λ””λ‘ κ°€ 이동 ν•΄μ„œ +와 -둜 좔가이동

μ΄λ ‡κ²Œ 세가지 경우둜 생각할 수 μžˆλ‹€.

λ¬Έμ œμ˜μ‘°κ±΄μ„ 보면, μ΄λ™ν•˜λ €κ³ ν•˜λŠ” 채널N은 500000와 κ°™κ±°λ‚˜ μž‘μ€μˆ˜λ‘œ μ œμ‹œλ˜μ§€λ§Œ, 이동할 수 μžˆλŠ” 채널은 λ¬΄ν•œλŒ€λ‹€. μ—¬κΈ°μ„œ λ‹¨μˆœν•˜κ²Œ 500000κΉŒμ§€ λ²”μœ„λ₯Ό 작으면 λ˜κ² μ§€ ν–ˆλ‹€κ°€ ν°μ½”λ‹€μΉœ μ‚¬λžŒμ΄ λ°”λ‘œ λ‚˜λ‹€!! πŸ˜ƒ

채널이 λ¬΄ν•œλŒ€λ‘œ μžˆλ‹€κ³  μ–ΈκΈ‰ν•΄μ€€ μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒ? 이동할 수 μžˆλŠ” λ²”μœ„κ°€, μ‘°κ±΄μ—μ„œ 주어진 500000보닀 λ„˜μ–΄κ°ˆ 수 도 μžˆλ‹€λŠ” λœ»μ΄λ‹€.
μ˜ˆμ‹œλ‘œ μ‚΄νŽ΄λ³΄μž.

채널 500000으둜 μ΄λ™ν•œλ‹€κ³  ν•  λ•Œ,
1μ—μ„œ 500000으둜 μ΄λ™ν•˜λŠ” 것보닀, 999000μ—μ„œ 500000으둜 μ΄λ™ν•˜λŠ” 것이 더 적은 λ²„νŠΌμ„ λˆ„λ₯΄κ³  이동할 수 μžˆλ‹€.

μ΄λŸ¬ν•œ 경우처럼, ν˜„μž¬ μˆ˜λ³΄λ‹€ 큰 수λ₯Ό λˆŒλŸ¬μ„œ 채널을 μ΄λ™ν–ˆμ„λ•Œ 더 효율적일 수 μžˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ, λ²”μœ„λ₯Ό μ΅œμ†Œ 1000000κΉŒμ§€ λ΄μ•Όν•œλ‹€. (μš°λ¦¬κ°€ 돌릴 수 μžˆλŠ” 채널은 50만 μ΄λ―€λ‘œ!)

λ‹€μ‹œ 그럼 λŒμ•„μ™€μ„œ, μœ„μ—μ„œ 적은 3가지 방식을 for문을 μ΄μš©ν•΄μ„œ μ™„μ „νƒμƒ‰μœΌλ‘œ ν’€μ–΄λ³΄μž

 

🟠 μ •λ‹΅μ½”λ“œ

  • solution() : λ©”μΈν•¨μˆ˜
  • pressCloseNumber() : μˆ«μžλ²„νŠΌμ„ λˆ„λ₯΄λŠ” 횟수λ₯Ό μ„Έμ–΄μ£ΌλŠ” ν•¨μˆ˜
  • for문을 돌린 이유 : 0λ²ˆλΆ€ν„° 1000000κΉŒμ§€ μ „λΆ€ λˆŒλŸ¬λ³΄λŠ” 것. μ΄λ™ν•΄μ•Όν•˜λŠ” μˆ˜κ°€ 100이어도, 1000이어도, 1000000이어도 λͺ¨λ“  수λ₯Ό νƒμƒ‰ν•œ ν›„, κ°€μž₯ μ΅œμ†Œλ‘œ λˆŒλ €μ§„ λ²„νŠΌ 횟수λ₯Ό 좜λ ₯ν•  수 μžˆλ„λ‘ ν•œλ‹€.
  • 처음 minCnt에 +와-둜만 이동가λŠ₯ν•œ 횟수λ₯Ό λ„£μ–΄μ€€λ‹€. abs(μ΄λ™ν•˜λ €λŠ”μ±„λ„n - μ‹œμž‘μ±„λ„100)
  • for 문을 μ΄μš©ν•΄μ„œ μ΅œμ†Œκ°’μ„ μ°Ύμ•„μ€€λ‹€. 
    • μ΅œμ†Œκ°’(+와 -만 λˆŒλŸ¬μ„œ λŒλ Έμ„λ•Œ vs. 채널1둜 돌리고 +-둜 μ‘°μ ˆν•œ 횟수)
    • μœ„μ—μ„œ λ„μΆœλœ μ΅œμ†Ÿκ°’ vs. 채널2둜 돌리고 +-둜 μ‘°μ ˆν•œ 횟수
    • μœ„μ—μ„œ λ„μΆœλœ μ΅œμ†Ÿκ°’ vs. 채널3으둜 돌리고 +-둜 μ‘°μ ˆν•œ 횟수 
    • .....
    • 100λ§ŒκΉŒμ§€ 진행
import Foundation

private func solution() {
    let n = Int(readLine()!)!
    let m = Int(readLine()!)!
    var brokenBtn = [Int]()
    if m != 0 {
        brokenBtn = readLine()!.split(separator: " ").map { Int($0)! }
    }

    // +-둜만 μ΄λ™ν•˜λŠ” 횟수
    var minCnt = abs(n - 100)

    // μˆ«μžλ²„νŠΌμ„ λˆŒλŸ¬μ„œ μ΄λ™ν•˜λŠ” 경우 μ „λΆ€ ν…ŒμŠ€νŠΈ
    // μˆ«μžλ²„νŠΌμœΌλ‘œ iλ₯Ό λˆŒλ €μ„ λ•Œλž‘, +-둜만 μ΄λ™ν• λ•Œλž‘ λΉ„κ΅ν•΄μ£ΌλŠ” λΆ€λΆ„
    for i in 0...1000000 {
        let pressNumButton = pressCloseNumber(n: i, brokenBtn: brokenBtn)

        if pressNumButton > 0 {
            let pressNumAndPlusMinus = abs(n - i) // 채널 i둜 μ΄λ™ν–ˆμœΌλ‹ˆκΉŒ, κ±°κΈ°μ„œ +-λˆŒλŸ¬μ£ΌλŠ” 횟수
            minCnt = min(minCnt, pressNumAndPlusMinus + pressNumButton)
        }
    }

    print(minCnt)
}

private func pressCloseNumber(n: Int, brokenBtn: [Int]) -> Int {
    var n = n

    if n == 0 {
        if brokenBtn.contains(n) {
            return 0
        } else {
            return 1
        }
    }

    var buttonPressCnt = 0
    while n > 0 {
        if brokenBtn.contains(n % 10) {
            return 0
        }

        n /= 10
        buttonPressCnt += 1
    }
    return buttonPressCnt
}

solution()
λ°˜μ‘ν˜•