본문 바로가기
알고리즘/백준

1041번 주사위

by 도쿠니 2022. 6. 21.

문제

풀이

큐브로 생각해서 풀면 쉽습니다. 문제의 주사위를 블록으로 호칭하겠습니다.

N 크기의 정육면체는 N=1 인 경우를 제외하고는 다음과 같이 구성됩니다.

  • 모서리 블록 + 모서리를 제외한 테두리 블록(N=2 제외)+ 테두리 안쪽 블록(N=2 제외)

각 부분의 블록이 보여주는 면은 다음과 같습니다.

  • 모서리 = 3면
  • 테두리 = 2면
  • 안쪽 = 1면

문제는 바닥면을 제외한 5 면의 최소합을 구하는 것입니다.

그러면 모서리, 테두리, 안쪽블록이 가질수 있는 면의 최소합을 구한 다음 각 구성의 개수만큼 곱해서 더해주면 됩니다.

int minOne; // 안쪽인 1면 최소합
int minTwo; // 테두리인 2면 최소합
int minThree; // 모서리인 3면 최소합

모서리의 경우 바닥면은 계산하지 않기 때문에 아래와 같은 식으로 구할 수 있습니다.

  • 3면의 최소합 * 위면의 모서리 블록 4개 + 2면의 최소합 * 아랫면의 모서리 블록 4개

테두리의 경우도 바닥면으로 인해서 다음과 같은 식으로 구할 수 있습니다.

  • 테두리(N)에서 모서리 2개를 제외한 개수 * ( 2면의 최소합 * 위와 옆면의 테두리블록 8개 + 1면의 최소합 * 아랫면의 테두리블록 4개)

안쪽의 경우 바닥면을 제외하고 구하면 됩니다.

  • 테두리에서 모서리 2개를 제외한 개수^2 * 바닥면을 제외한 면의 개수인 5 * 1면의 최소합
// 모서리
long edges = 4L * (minThree + minTwo);

// 테두리
long borders =  (N-2) * (long)(minTwo * 8 + minOne * 4);

// 안쪽
long inners = (long)(N-2) * (N-2) * 5 * minOne;

// 정답
long answer = edges + borders + inners;

식을 구했으니 이제 면의 최소합을 구하면됩니다.

 

  • 3면의 경우
    • 붙어있는 3면은 정육면체 총 6면 중에 서로 마주보지않는 면을 제외한 3면입니다.
    • A =1 ~ F = 6 으로 치환하여 경우의 수를 나열해 보겠습니다. 
      • 1 2 3
      • 1 2 4
      • 1 5 3
      • 1 5 4
      • 6 2 3
      • 6 2 4
      • 6 5 3
      • 6 5 4
    • 위의 경우의 수를 확인해보면 마주보는 면끼리는 같이 있지 않습니다.
    • 1 - 6 / 2 - 5 / 3 - 4 가 서로 마주보기 때문에 각각 작은 면을 구해 3면을 더해주면 됩니다.
  • 2면의 경우
    • 한 면을 기준으로 마주보는 면을 제외한 모든 면과 조합할 수 있습니다.
    • 여기서는 최소합을 구해야하기 때문에 위에서 구한 것을 이용합니다.
    • 마주보는 면 3가지 중 작은 경우 2가지를 더합니다.
  • 1면의 경우
    • 제일 작은 면을 구합니다.

코드로 보면 더 쉽게 이해할 수 있습니다.

면의 최소합과 공식을 구했으니 코드로 옮겨보겠습니다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine());

        StringTokenizer st = new StringTokenizer(br.readLine());
        
        int[] dice = new int[6];
        
        int sum = 0;
        int max = 0;

        for (int i = 0; i < 6; i++) {
            int num = Integer.parseInt(st.nextToken());

            dice[i] = num;
            
            sum += num;
            max = Math.max(max, num);
        }
        
        if (N == 1) {
            System.out.println(sum - max);
            return;
        }
        
        ArrayList<Integer> minTwoList = new ArrayList<>();

        for (int i = 0; i < 3; i++) {
            minTwoList.add(Math.min(dice[i], dice[5 - i]));
        }
        
        Collections.sort(minTwoList);
        
        int minOne = minTwoList.get(0);
        int minTwo = minTwoList.get(0) + minTwoList.get(1);
        int minThree = minTwoList.get(0) + minTwoList.get(1) + minTwoList.get(2);
        
        // 모서리
        long edges = 4L * (minThree + minTwo);

        // 테두리
        long borders =  (N-2) * (long)(minTwo * 8 + minOne * 4);

        // 안쪽
        long inners = (long)(N-2) * (N-2) * 5 * minOne;

        // 정답
        long answer = edges + borders + inners;

        System.out.println(answer);
    }

}

자바 80ms

 

'알고리즘 > 백준' 카테고리의 다른 글

단계별로 풀어보기 - 입출력과 사칙연산  (0) 2022.06.02

댓글