본문 바로가기
  • 책과 글
알고리즘/삼성

삼성 코딩테스트 기출_(백준)주사위 굴리기

by twfnm67 2019. 9. 25.

난이도 ★☆

 

문제출처

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

 

14499번: 주사위 굴리기

첫째 줄에 지도의 세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 그리고 명령의 개수 K (1 ≤ K ≤ 1,000)가 주어진다. 둘째 줄부터 N개의 줄에 지도에 쓰여 있는 수가 북쪽부터 남쪽으로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 주사위를 놓은 칸에 쓰여 있는 수는 항상 0이다. 지도의 각 칸에 쓰여 있는 수는 10을 넘지 않는 자연수 또는 0이다. 마

www.acmicpc.net

포인트

1. 주사위

주사위는 여섯 개의 면과 현재 위치 정보(행, 열)를 속성으로 가지는 구조체로 구현하였다.

(필자는 문제에서 주어진 주사위 면의 번호와 다른 방식으로 번호를 매겼다. 문제에서의 1, 2, 3, 4, 5, 6번 면을 본인은 1, 4, 5, 6, 2, 3으로 매긴 후 문제를 풀기 시작하였기에, 필자가 구현한 구조체의 one, two, three, four, five, six는 실제 문제에서 주어진 1, 5, 6, 2, 3, 4번 면과 매핑된다. --> 번호를 매기는 것은 각자가 정하면 되는 부분이므로 무시해도 좋음)

 

2. 주사위 굴리기

주사위는 총 네 개의 방향으로 굴릴 수 있으므로 switch문에 각각의 방향을 case로 넣어서 구현하였다.

방향이 바뀌면 면이 바뀌므로 각각의 면을 재설정해주는 과정만 거치면 되나, 범위를 넘어가면 주사위를 굴릴 수 없으므로 범위 체크를 먼저 한다. 그리고 boolean값을 반환값으로 하여, 주사위가 굴려졌을 경우에만 main에서 출력이 되게끔 구현하였다.

 

3. 번호 바꾸기

이 역시, main에서 주사위가 굴려졌을 경우에만 실행되는 함수이다. 주사위를 굴린 후 주사위와 지도의 번호를 체크하고 바꾸어주는 함수이다.

주의할 점은, 지도의 번호를 주사위에 옮길 시에, 지도의 번호는 0이 된다는 점이다.(실제로 이 부분을 놓쳐서 계속 틀린 답이 나와서 애먹은 기억..)

 

+추가) 문제에서 행을 x로 받고 열을 y로 받고 있다. 필자는 x,y를 쓰지 않고 r, c를 쓰기 때문에 이 부분을 크게 신경쓰지 않았으나, 실제로 이 부분에서 잘못 구현한 사례가 많다고 하니 주의해야 한다.

 

 

정답코드

#include <iostream>
using namespace std;

int N, M, R, C, K;
int map[25][25];

struct side {
	int r;
	int c;
	int one;
	int two;
	int three;
	int four;
	int five;
	int six;
};//주사위의 위치 정보(r, c)와 여섯 개의 면 

side dice;//주사위 하나 선언

bool move(int dir) {//주사위 굴리기
	bool moved = false;
	switch (dir) {
	case 1://동
		if (dice.c + 1 < M) {//범위체크 먼저 해주기
			dice.c += 1;//주사위 한 칸 이동
			int one = dice.six;
			int three = dice.five;
			int five = dice.one;
			int six = dice.three;
			dice.one = one;
			dice.three = three;
			dice.five = five;
			dice.six = six;//위치 바뀌는 면 모두 바꿔주기
			moved = true;//주사위가 움직여진 것이므로 true값 반환
		}
		break;
	case 2://서
		if (dice.c - 1 >= 0) {
			dice.c -= 1;
			int one = dice.five;
			int three = dice.six;
			int five = dice.three;
			int six = dice.one;
			dice.one = one;
			dice.three = three;
			dice.five = five;
			dice.six = six;
			moved = true;
		}
		break;
	case 3://북
		if (dice.r - 1 >= 0) {
			dice.r -= 1;
			int one = dice.two;
			int two = dice.three;
			int three = dice.four;
			int four = dice.one;
			dice.one = one;
			dice.two = two;
			dice.three = three;
			dice.four = four;
			moved = true;
		}
		break;
	case 4://남
		if (dice.r + 1 < N) {
			dice.r += 1;
			int one = dice.four;
			int two = dice.one;
			int three = dice.two;
			int four = dice.three;
			dice.one = one;
			dice.two = two;
			dice.three = three;
			dice.four = four;
			moved = true;
		}
		break;
	}
	return moved;
}

void changeNum() {//주사위와 지도 번호 바꾸기(주사위가 이동한 경우에만 실행됨)
	int curR = dice.r;
	int curC = dice.c;
	if (map[curR][curC] == 0) {
		map[curR][curC] = dice.three;
	}
	else {
		dice.three = map[curR][curC];
		map[curR][curC] = 0;//지도의 번호가 주사위로 옮겨진 후에는 지도의 숫자가 0이 됨을 주의
	}
}

int main() {
	cin >> N >> M >> R >> C >> K;
	dice.r = R;
	dice.c = C;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> map[i][j];
		}
	}

	while (K--) {
		int dir;
		cin >> dir;
		if (move(dir)) {
			changeNum();
			cout << dice.one << '\n';
		}
	}

	return 0;
}

댓글