플랫폼 | 번호 | 제목 | 유형 | 난이도 | 언어 |
---|---|---|---|---|---|
백준 | 2116 | 주사위 쌓기 | 완전탐색 | 골드5 | Swift |
이 문제를 처음 읽어보면 움칫한다. (어떻게 하라는 걸까?)
특별한 것은 없다. 완전탐색(브루트포스)로 모든 경우의 수를 확인하면 된다.
가장 중요한 것은 1번(가장 아래) 주사위이다. 그래서 1번 주사위의 모든 각 면이 바닥을 향할 때 규칙에 맞게 주사위를 쌓고 기둥 한 면의 최댓값을 구하면 된다.
[5개 주사위 예제]
1. 1번 주사위의 0번 인덱스 숫자를 바닥면으로 정한다.
2. 1번 주사위의 윗면 숫자를 구한다.
3. 1번 주사위의 사이드(바닥,위면 제외) 숫자들을 구해 sides 배열 저장한다.
(반복문 2번~5번 주사위)
4. 2번 주사위의 바닥 숫자는 1번 주사위의 윗면 숫자이다.
5. 2번 주사위의 윗면 숫자를 구한다.
6. 2번 주사위의 사이드 숫자들을 구해 sides 배열에 저장한다.
(3~5번 주사위도 위와 같이 반복하여 사이드 숫자들을 구한다)
그러면 sides에는 [1번 주사위 사이드, 2번 주사위 사이드, 3번 주사위 사이드 ...]가 저장 된다.
이제 각 주사위 사이드에서 최대값을 골라낸다.
[1번 사이드 최대값, 2번 사이드 최대값, 3번 사이드 최대값 ...] 이를 모두 더하면 답이 된다!!
let N = Int(readLine()!)!
var dices: [[Int]] = []
for _ in 0..<N {
dices.append(readLine()!.split(separator: " ").map{ Int($0)! })
}
// 주사위의 반대편 숫자를 구하는 함수
func getOppositeNum(currentNum: Int, dice: [Int]) -> Int {
let idx = dice.firstIndex(of: currentNum)
switch idx {
case 0: return dice[5]
case 1: return dice[3]
case 2: return dice[4]
case 3: return dice[1]
case 4: return dice[2]
case 5: return dice[0]
default: return 0
}
}
// 주사위에서 밑면, 위면을 제외한 사이드 숫자들을 구하는 함수
func getSideNums(bottomNum: Int, upperNum: Int, dice: [Int]) -> [Int] {
var pDice = dice
pDice.remove(at: pDice.firstIndex(of: bottomNum)!)
pDice.remove(at: pDice.firstIndex(of: upperNum)!)
return pDice
}
var result: [Int] = []
for i in 0..<6 {
var sides: [[Int]] = []
var bottomNum = dices[0][i]
var upperNum = getOppositeNum(currentNum: bottomNum, dice: dices[0])
sides.append(getSideNums(bottomNum: bottomNum, upperNum: upperNum, dice: dices[0]))
for j in 1..<N {
bottomNum = upperNum
upperNum = getOppositeNum(currentNum: bottomNum, dice: dices[j])
sides.append(getSideNums(bottomNum: bottomNum, upperNum: upperNum, dice: dices[j]))
}
result.append(sides.map{ $0.max()! }.reduce(0, +))
}
print(result.max()!)
처음에는 복잡해 보여 당황했지만 규칙에 맞게 해보니 생각하는 데로 풀렸다. 당황하지 말고 성실하게 풀자!!