Algorithm/java

[백준, Java] 2116번 주사위 쌓기

나연쓰 2025. 1. 21. 15:38

 

 

 

문제풀이

브루트포스 알고리즘으로 완전 탐색해야하는 문제이다.

 

BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine());

int N = Integer.parseInt(st.nextToken());
arr = new int[N][6];

int max = Integer.MIN_VALUE;

for(int i=0; i<N; i++) {
    st = new StringTokenizer(bf.readLine());
    for(int j=0; j<6; j++) {
        arr[i][j] = Integer.parseInt(st.nextToken());
    }
}

1. 문제에서 주어진 입력을 받는다. 배열의 크기는 행 : N , 열 : 6 (주사위는 6면) 이다.

변수 max는 최대값을 담기 위한 변수이다.

 

for(int i=0; i<6; i++) {
    int sum = 0;
    int top = i;
    int bottom = checkTop(i);

2. 반복은 전체적으로 6번을 해야한다.

이유는 주사위의 눈은 총 6개(1,2,3,4,5,6)이므로 각각 주사위의 윗면에 올라왔을 때에 따라 나눠서 비교해야하기 때문이다.(사진 참고)

sum은 최대값을 더할 변수이고, 주사위의 윗면과 아랫면에 대한 인덱스 값을 담을 변수를 생성한다.

 

sum += checkBeside(0, top, bottom);

3. checkBeside 함수로 옆면의 값들 중 가장 큰 값을 구한다.

매개변수는 총 3개이다.

첫 번째 매개변수는 몇 번째 주사위에 해당하는지(현재 0이 의미하는것은 1번 주사위를 의미),

두 번째 매개변수인 top은 현재 주사위의 윗면 인덱스 값,

세 번째 매개변수인 bottom은 현재 주사위의 아랫면 인덱스 값이다.

 

private static int checkBeside(int idx, int a, int b) {
    int maxValue = 0;
    for(int i=0; i<6; i++) {
        if(i != a && i != b) {
            maxValue = Math.max(maxValue, arr[idx][i]);
        }
    }
    return maxValue;
}

4. checkBeside 함수에서는 현재 주사위의 옆면 값(총 4개) 중 가장 큰 값을 return 한다.

매개변수 a,b는 각각 주사위의 윗면 인덱스 값, 아랫면 인덱스 값이기 때문에 이에 해당하지 않는 값들만 비교한다.

 

for(int j=1; j<N; j++) {
//				top과 같은 숫자를 갖는게 몇 번째 인덱스에 있는지 찾기.
    for(int k=0; k<6; k++) {
        if(arr[j][k] == arr[j-1][top]) {
            bottom = k;
            top = checkTop(bottom);

            sum += checkBeside(j, top, bottom);
            break;
        }
    }



}

5. 다음 반복은 1부터 N번까지 반복한다.

1~N이 의미하는 것은 총 N개의 주사위가 있으면 1번 주사위를 제외한 나머지 주사위에 대해 반복하는 것이다.

(1번 주사위는 3,4번에서 실행했음.)

 

1번 주사위의 윗면의 값에 따라서 나머지 N-1개의 주사위들은 자동으로 값이 결정된다.

 

반복문이 한 번 더 실행되는데 이 때의 반복문은 1번 주사위 윗면의 숫자는 2번 주사위 아랫면의 숫자가 같아야하기 때문에 1번 주사위 윗면의 숫자가 2번 주사위의 몇 번째 인덱스에 있는지 찾기 위함이다.

조건을 만족해 찾았다면 bottom과 top의 값을 갱신한다.

그리고 윗면과 아랫면의 인덱스를 찾았으니 checkBeside 함수로 최대값을 갖는 옆 면의 값을 찾는다.

 

max = Math.max(max, sum);

6. 5번을 반복하면 sum에는 N개의 주사위 옆면에 대한 합의 최댓값이 들어있을 것이다.

우리는 이를 총 6번 반복해야하기 때문에 한 주사위 사이클에 대한 반복이 끝날 때마다 최댓값을 갱신해준다.

 

System.out.println(max);

7. 결과를 출력한다.

 

 

 

코드

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

public class Main {
	static int[][] arr;
	public static void main(String[] args) throws IOException {
		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(bf.readLine());
		
		int N = Integer.parseInt(st.nextToken());
		arr = new int[N][6];
		
		int max = Integer.MIN_VALUE;
		
		for(int i=0; i<N; i++) {
			st = new StringTokenizer(bf.readLine());
			for(int j=0; j<6; j++) {
				arr[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
//		첫번째 주사위에 대해 6번 반복
		for(int i=0; i<6; i++) {
			int sum = 0;
			int top = i;
			int bottom = checkTop(i);
			
			sum += checkBeside(0, top, bottom);
			
//			총 N개의 주사위 중 N-1개의 주사위를 반복해야함.
			for(int j=1; j<N; j++) {
//				top과 같은 숫자를 갖는게 몇 번째 인덱스에 있는지 찾기.
				for(int k=0; k<6; k++) {
					if(arr[j][k] == arr[j-1][top]) {
						bottom = k;
						top = checkTop(bottom);
						
						sum += checkBeside(j, top, bottom);
						break;
					}
				}
				
				
				
			}
//			최댓값 비교
			max = Math.max(max, sum);
		}
		System.out.println(max);
	}
	private static int checkTop(int i) {
		int bottom = 0;
		if(i == 0) bottom = 5;
		else if( i == 1) bottom = 3;
		else if( i == 2) bottom = 4;
		else if( i == 3) bottom = 1;
		else if( i == 4) bottom = 2;
		else if( i == 5) bottom = 0;
		
		return bottom;
		
	}
	private static int checkBeside(int idx, int a, int b) {
		int maxValue = 0;
		for(int i=0; i<6; i++) {
			if(i != a && i != b) {
				maxValue = Math.max(maxValue, arr[idx][i]);
			}
		}
		return maxValue;
	}
}

 

 

 

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