문제
+---+
| D |
+---+---+---+---+
| E | A | B | F |
+---+---+---+---+
| C |
+---+
주사위는 위와 같이 생겼다. 주사위의 여섯 면에는 수가 쓰여 있다. 위의 전개도를 수가 밖으로 나오게 접는다.
A, B, C, D, E, F에 쓰여 있는 수가 주어진다.
지민이는 현재 동일한 주사위를 N3개 가지고 있다. 이 주사위를 적절히 회전시키고 쌓아서, N×N×N크기의 정육면체를 만들려고 한다. 이 정육면체는 탁자위에 있으므로, 5개의 면만 보인다.
N과 주사위에 쓰여 있는 수가 주어질 때, 보이는 5개의 면에 쓰여 있는 수의 합의 최솟값을 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. 둘째 줄에 주사위에 쓰여 있는 수가 주어진다. 위의 그림에서 A, B, C, D, E, F에 쓰여 있는 수가 차례대로 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, 쓰여 있는 수는 50보다 작거나 같은 자연수이다.
출력
첫째 줄에 문제의 정답을 출력한다.
내가 푼 풀이
- 주어진 n^3개의 주사위를 적당히 회전시켜서 쌓아 올린 n * n * n크기의 정육면체를 만들때의 보이는 5개면의 합 최솟값을 구한다.
- 바닥과 마주본 면은 보이지 않으므로 합에서 제외된 5개의 면이다.
- 주사위를 쌓아올렸을때, 보이는 면의개수의 경우의 수는 3가지이다.
- 주사위의 3개의 면이 보이는경우, 2개의 면이 보이는 경우, 1개의 면이 보이는 경우 이다.
- 해당 3가지 경우의수 모두 최솟값으로 구한다면, 쌓아 올린 정육면체의 5개면의 합이 최솟값이 된다.
- 처음에는 노가다로 주사위의 면 하나를 기준으로 했을 때, 3개의 면이 보이는 경우의 수를 모두 구하고, 중복되는 값을 소거했다.
- 2개의 면을 구할때도 모든 경우의 수를 구하고 중복된 경우의 수를 제거하여서 구한 값 중 최솟값을 구했다.
- 3가지 경우의 수를 구했다면 n * n * n 의 정육면체에서 이전에 경우의 수가 몇 개나 구성되어 있는지 파악한다.
- 3개의 면이 보이는 주사위 개수 : 4개
- 2개의 면이 보이는 주사위 개수 : 4 * (N-1) + 4 *(N-2)
- 1개의 면이 보이는 주사위 개수: 4 * (N-1) * (N-2) + 4 * (N-2)^2
모든 경우의수를 노가다로 구했을 때의 코드는 다음과 같다.
let n = Int(readLine()!)!
var arr = readLine()!.split(separator: " ").map{ Int($0)! }
var num3 = [Int]()
var num2 = [Int]()
// ABC ABD ACE ADE
// BDF BCF CEF DEF
num3 = [arr[0] + arr[1] + arr[2],
arr[0] + arr[1] + arr[3],
arr[0] + arr[2] + arr[4],
arr[0] + arr[3] + arr[4],
arr[1] + arr[3] + arr[5],
arr[1] + arr[2] + arr[5],
arr[2] + arr[4] + arr[5],
arr[3] + arr[4] + arr[5]
]
// AB AC AD AE
// BC BD BF CF
// CE DE DF EF
num2 = [arr[0] + arr[1],
arr[0] + arr[2],
arr[0] + arr[3],
arr[0] + arr[4],
arr[1] + arr[2],
arr[1] + arr[3],
arr[1] + arr[5],
arr[2] + arr[5],
arr[2] + arr[4],
arr[3] + arr[4],
arr[3] + arr[5],
arr[4] + arr[5]
]
var num3Min = num3.min()!
var num2Min = num2.min()!
var num1Min = arr.min()!
if n == 1 {
print(arr.reduce(0, +) - arr.max()!)
} else {
print(num3Min * 4 + num2Min * ((n-1) * 4 + (n-2) * 4) + num1Min * (4 * (n-1) * (n-2) + (n-2) * (n-2)))
}
해당 코드는 정답이 떴지만 주사위의 원리를 좀 이용해보려 한다.
A와 마주 보는 면은 F
B와 마주보는면은 E
C와 마주보는면은 D이다.
3면이 보이는 주사위를 회전시켜서 보일 때, 각 보이는 면과 마주 보는 면은 같이 보일 수 없다.
따라서 3면이 보이는 숫자를 최소로 만들려면 위의 세 가지를 모두 더한 값을 최솟값으로 만들면 된다.
2면이 보이는 주사위도 마찬가지로 위에 세 가지 중 작은 두 가지를 더한 값이 최솟값이 된다.
이를 코드로 구현하면 다음과 같다.
import Foundation
let n = Int(readLine()!)!
var arr = readLine()!.split(separator: " ").map{ Int($0)! }
var min1 = min(arr[0], arr[5])
var min2 = min(arr[1], arr[4])
var min3 = min(arr[2], arr[3])
var sortedArr = [min1, min2, min3].sorted{ $0 < $1}
var num1Min = sortedArr[0]
var num2Min = sortedArr[0] + sortedArr[1]
var num3Min = sortedArr[0] + sortedArr[1] + sortedArr[2]
if n == 1 {
print(arr.reduce(0, +) - arr.max()!)
} else {
var result = 0
result += num3Min * 4
result += (num2Min * (n-1) * 4 + num2Min * (n-2) * 4)
result += (num1Min * (n-1) * (n-2) * 4 + num1Min * (n-2) * (n-2))
print(result)
}
'코딩테스트 > 백준' 카테고리의 다른 글
BOJ-1890 점프 Swift (0) | 2023.06.13 |
---|---|
BOJ-7562 나이트의 이동 Swift (1) | 2023.06.12 |
BOJ-2096 내려가기 Swift (0) | 2023.06.12 |
BOJ-11725 트리의 부모 찾기 Swift (1) | 2023.06.11 |
BOJ-11497 통나무 건너뛰기 Swift (0) | 2023.06.11 |