BOJ 1041 주사위
https://www.acmicpc.net/problem/1041
문제
1
2
3
4
5
6
7
+---+
| 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보다 작거나 같은 자연수이다.
출력
첫째 줄에 문제의 정답을 출력한다.
예제 입력 1
2 1 2 3 4 5 6
예제 출력 1
36
예제 입력 2
3 1 2 3 4 5 6
예제 출력 2
69
… 이하 예제 생략
코드
이번 코드는 조금 복잡해 보이게 작성한 것 같다.
주사위를 쌓아올려 만든 정육면체에서 각 주사위가 보이는 면의 수는 다르다.
단순히 한 면만 보이는 주사위, 정육면체에서 모서리쪽에 있는 두 면이 보이는 주사위, 정육면체에서 꼭지점에 있는 세 면이 보이는 주사위가 있다.
내가 푼 방법은 위와 같이 한 주사위에서 한 면, 두 면, 세 면에 적혀있는 각각의 수가 최소가 되는 경우를 구하고, 정육면체에서 보이는 면의 수를 합한 수를 도출하는 방법이다.
나는 두 면의 수를 구하는 경우들의 규칙성을 발견하지 못해서 하드코딩으로 직접 면들을 더해가며 풀었고, 이 부분이 약간 마음에 들지 않는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static final int NUMBER_OF_SIDE = 6;
static final int[][] TWO_SIDES = {
{0, 1}, {0, 2}, {0, 3}, {0, 4},
{1, 2}, {1, 3}, {1, 5},
{2, 4}, {2, 5},
{3, 4}, {3, 5},
{4, 5}
};
static final int[][] PARALLEL_SIDES = {
{0, 5}, {1, 4}, {2, 3}
};
static long N;
static int[] sides = new int[NUMBER_OF_SIDE];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < NUMBER_OF_SIDE; i++) {
sides[i] = Integer.parseInt(st.nextToken());
}
// N이 1일 때는, 주사위에서 가장 큰 수인 바닥면을 제외한 나머지를 더해야 한다.
if(N == 1) {
Arrays.sort(sides);
int answer = 0;
for (int i = 0; i < NUMBER_OF_SIDE - 1; i++) {
answer += sides[i];
}
System.out.println(answer);
return;
}
long answer = calculateMinSumOfSides();
System.out.println(answer);
}
static long calculateMinSumOfSides() {
int minSingleSide = Arrays.stream(sides).min().getAsInt();
int minTwoSides = calculateMinSumOfTwoSides();
int minThreeSides = calculateMinSumOfThreeSides();
long minSum = 0;
minSum += minThreeSides * 4;
minSum += minTwoSides * (N * 8 - 12);
minSum += minSingleSide * (Math.pow(N, 2) * 5 - N * 16 + 12);
return minSum;
}
static int calculateMinSumOfTwoSides() {
int minTwoSides = Integer.MAX_VALUE;
for (int[] check: TWO_SIDES) {
int sum = sides[check[0]] + sides[check[1]];
minTwoSides = Integer.min(minTwoSides, sum);
}
return minTwoSides;
}
static int calculateMinSumOfThreeSides() {
int minThreeSides = 0;
for (int[] check: PARALLEL_SIDES) {
int minSide = Integer.min(sides[check[0]], sides[check[1]]);
minThreeSides += minSide;
}
return minThreeSides;
}
}