Post

[ 백준 2818 ] 숙제하기 싫을 때 : C++ 풀이

백준 2818 풀이입니다.

[ 백준 2818 ] 숙제하기 싫을 때 : C++ 풀이

풀이

결국엔 어떻게 돌리느냐는 위 아래 눈이 무엇인지 가 중요 합니다.

내말은 돌려도 변하지 않는 면이 있는데, 그 면들을 중심으로 번호가 어떻게 변하는지 4개의 수의 반복이 어케되는지를 매겨놓으면 문제해결이 가능합니다.

처음 주사위 상태는

1
2
3
4
5
5 (굴려도 변하지 않는 앞쪽면)

1 (윗면)

2 (굴려도 변하지 않는 뒤쪽면)

이렇게 되고, 주사위를 굴리다가 다음 행으로 옮기게 되면 주사위의 상태는 아래처럼 변할 것입니다.

1
2
3
4
5
(마지막 윗면 상태 의 반대편)

(이전 윗면)

(마지막 윗면 상태)

또 그 다음은

1
2
3
4
5
(마지막 윗면 상태의 반대편)

N

(마지막 윗면상태)

이런식으로 반복됨을 알 수 있습니다.

그렇다면, 1 4 6 3과 같은 옆면의 수열을 어떻게 구할 수 있느냐가 이제 관건인데, 사실 주사위기 때문에 경우의 수가 그렇게 많지 않습니다.

저의 경우는 아예 계산을 해서 프리셋을 먼저 생성해놓고 풀었는데요, 아래와 같이 반복되는 수열이 정의됩니다.

! 오른쪽으로 굴리는 기준 !

1
2
3
4
5
6
(5, 2) 일 경우 {1, 4, 6, 3}
(2, 5) 일 경우 {1, 3, 6, 4}
(1, 6) 일 경우 {3, 2, 4, 5}
(6, 1) 일 경우 {3, 5, 4, 2}
(3, 4) 일 경우 {1, 5, 6, 2}
(4, 3) 일 경우 {1, 2, 6, 5}

구상한 알고리즘

행이 홀수일 경우

  1. (a, b) 값을 얻는다. (이때 a와 b는 수열에 관여하지 않는 위에서 봤을때 기준 주사위의 앞, 뒷면 이다.)

  2. 이전 판의 a 값을 가져온다. 이 값이 현재 상태의 윗면이다.

  3. 열의 크기를 4로 나눈 몫과 14(전체 수열의 투어 결과)를 곱한 값을 결과에 더한다.

  4. 열의 크기를 4로 나눈 나머지값만큼 더 굴린다. while(remain--) {} 굴리는 원리는 첫 윗면의 idx 값을 가져와서, idx = (idx + 1) % 4; 와 같은 방식으로 더해나가면 된다.

행일 짝수일 경우

  • 수열을 얻는 과정은 똑같이 진행하나, idx = (idx - 1 >= 0 ? idx - 1 : 3) % 4; 과 같이 전개하면 된다.

소스코드

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
#include<iostream>
#include<vector>
using namespace std;

vector<int> preset[7][7];

int main() {
	int front = 5, back = 2;
	int up = 1;
	preset[5][2] = { 1, 4, 6, 3 };
	preset[2][5] = { 1, 3, 6, 4 };
	preset[1][6] = { 3, 2, 4, 5 };
	preset[6][1] = { 3, 5, 4, 2 };
	preset[3][4] = { 1, 5, 6, 2 };
	preset[4][3] = { 1, 2, 6, 5 };

	int n, m; cin >> n >> m;

	long long ans = 0;

	for (int i = 1; i <= n; ++i) {
		ans += (m / 4) * 14;
		int remain = m % 4;
		int idx = -1;
		
		for (int i = 0; i < 4; ++i) {
			if (preset[front][back][i] == up) {
				idx = i;
			}
		}

		while (remain--) {
			int next_value = preset[front][back][idx];
			ans += next_value;
			if (remain) {
				if(i%2) idx = (idx + 1) % 4;
				else idx = (idx - 1 >= 0 ? idx - 1 : 3) % 4;
			}
		}

		int tmp = front;
		back = preset[front][back][idx];
		up = tmp;
		front = 7 - back;
	}
	cout << ans;
}
This post is licensed under CC BY 4.0 by the author.