정육면체 한번 더 굴리기 [2021-하반기 오전 1번 문제]

문제 링크

삼성 코딩테스트 기출 문제: 정육면체 한번 더 굴리기 | 코드트리
주요 IT 기업의 코딩테스트 기출 문제를 연습하며 실전 감각을 키우세요. 취업 합격률을 높이는 필수 연습 과정입니다.

문제 설명

1-6의 숫자가 써져있는 nn 격자판 위에 11 정육면체가 놓여있음. 처음 정육면체의 각 면에는 1부터 6까지의 숫자가 쓰여져 있고, m번에 걸쳐 주사위를 계속 1칸씩 굴림. 마주보는 면의 합은 정확히 7임. 처음 위치는 (0,0)에 있고, 처음에는 항상 오른쪽으로 움직임. 점수는 놓여져 있는 칸의 숫자와 인접한 칸들의 합 만큼 숫자를 얻음. 주사위가 굴려지고 나면, 보드의 해당 칸의 숫자보다 주사위 아랫면이 크면 90도 시계방향으로 회전하고, 작다면 반시계방향 회전함. 만약 격자를 벗어난다면, 방향이 정반대로 움직임. m번 진행 후의 결과를 구하기.

해결 방법

방향 수정주사위가 굴려지고 나면, 보드의 해당 칸의 숫자보다 주사위 아랫면이 크면 90도 시계방향으로 회전하고, 작다면 반시계방향 회전한다.

void set_dir() {
	int cur = 7 - dice[0];
	if (cur > arr[x][y]) {
		dir = (dir + 1) % 4;
	}
	else if (cur < arr[x][y]) {
		dir = (dir + 3) % 4;
	}
}

점수 획득하기점수는 놓여져 있는 칸의 숫자와 인접한 칸들의 합 만큼 숫자를 얻는다. BFS + 큐로 해결하면 된다.

int visited[21][21];
void get_score() {
	memset(visited, 0, sizeof(visited));
	visited[x][y] = 1;
	queue<pair<int, int>> que;
	que.push({ x,y, });

	int cx, cy, nx, ny;
	while (!que.empty()) {
		tie(cx, cy) = que.front();
		score += arr[x][y];
		que.pop();
		for (int i = 0;i < 4;i++) {
			nx = cx + dx[i], ny = cy + dy[i];
			if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
			if (visited[nx][ny]) continue;
			if (arr[nx][ny] != arr[cx][cy]) continue;
			visited[nx][ny] = 1;
			que.push({ nx,ny });
		}
	}
}

주사위 굴리기주사위의 면을 움직인 부분에 맞춰서 수정해준다. 이 부분이 이 문제의 핵심인데, 마주보는 면의 합이 정확히 7이라는 것만 기억하면 된다.

void set_dice() {
	int tmp_dice[3];

	if (dir == 0) {
		tmp_dice[0] = 7 - dice[2], tmp_dice[1] = dice[1], tmp_dice[2] = dice[0];
	}
	else if (dir == 1) {
		tmp_dice[0] = 7 - dice[1], tmp_dice[1] = dice[0], tmp_dice[2] = dice[2];
	}
	else if (dir == 2) {
		tmp_dice[0] = dice[2], tmp_dice[1] = dice[1], tmp_dice[2] = 7 - dice[0];
	}
	else {
		tmp_dice[0] = dice[1], tmp_dice[1] = 7 - dice[0], tmp_dice[2] = dice[2];
	}

	for (int i = 0;i < 3;i++) {
		dice[i] = tmp_dice[i];
	}
}

주사위 위치 이동주사위의 위치를 이동시키고, 격자를 벗어나면 방향을 정반대로 해서 움직인다.

void roll_dice() {
	int nx, ny;
	nx = x + dx[dir], ny = y + dy[dir];
	if (nx < 0 || ny < 0 || nx >= n || ny >= n) {
		dir = (dir + 2) % 4;
		nx = x + dx[dir], ny = y + dy[dir];
	}
	x = nx, y = ny;

}

전체적으로 평이한 문제다.

전체 코드

#include <iostream>
#include <queue>
#include <tuple>
#include <cstring>
using namespace std;

int n, m;
int arr[21][21];

int dice[3] = { 1,2,3 }; // 상 , 남, 동 

int x, y, dir;
int score = 0;

int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };

void input() {
	cin >> n >> m;

	for (int i = 0;i < n;i++) {
		for (int j = 0;j < n;j++) {
			cin >> arr[i][j];
		}
	}

	x = 0, y = 0, dir = 0;
}

void roll_dice() {
	int nx, ny;
	nx = x + dx[dir], ny = y + dy[dir];
	if (nx < 0 || ny < 0 || nx >= n || ny >= n) {
		dir = (dir + 2) % 4;
		nx = x + dx[dir], ny = y + dy[dir];
	}
	x = nx, y = ny;

}

void set_dice() {
	int tmp_dice[3];

	if (dir == 0) {
		tmp_dice[0] = 7 - dice[2], tmp_dice[1] = dice[1], tmp_dice[2] = dice[0];
	}
	else if (dir == 1) {
		tmp_dice[0] = 7 - dice[1], tmp_dice[1] = dice[0], tmp_dice[2] = dice[2];
	}
	else if (dir == 2) {
		tmp_dice[0] = dice[2], tmp_dice[1] = dice[1], tmp_dice[2] = 7 - dice[0];
	}
	else {
		tmp_dice[0] = dice[1], tmp_dice[1] = 7 - dice[0], tmp_dice[2] = dice[2];
	}

	for (int i = 0;i < 3;i++) {
		dice[i] = tmp_dice[i];
	}
}

int visited[21][21];
void get_score() {
	memset(visited, 0, sizeof(visited));
	visited[x][y] = 1;
	queue<pair<int, int>> que;
	que.push({ x,y, });

	int cx, cy, nx, ny;
	while (!que.empty()) {
		tie(cx, cy) = que.front();
		score += arr[x][y];
		que.pop();
		for (int i = 0;i < 4;i++) {
			nx = cx + dx[i], ny = cy + dy[i];
			if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
			if (visited[nx][ny]) continue;
			if (arr[nx][ny] != arr[cx][cy]) continue;
			visited[nx][ny] = 1;
			que.push({ nx,ny });
		}
	}
}

void set_dir() {
	int cur = 7 - dice[0];
	if (cur > arr[x][y]) {
		dir = (dir + 1) % 4;
	}
	else if (cur < arr[x][y]) {
		dir = (dir + 3) % 4;
	}
}

void solve() {
	roll_dice();
	set_dice();
	get_score();
	set_dir();
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
//	freopen("sample_input.txt", "r", stdin);

	input();
	for (int i = 0;i < m;i++) {
		solve();
	}
	cout << score;
}