• Home
  • About
    • 코드좀비 photo

      코드좀비

      An amazing website.

    • Learn More
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

[BOJ] 백준 14499 주사위 굴리기 간단한설명과 코드 C++

29 Dec 2019

Reading time ~4 minutes

문제 정보

백준 ( BOJ ) 14499 주사위 굴리기

문제 풀이 : 시뮬레이션

문제 출처 : https://www.acmicpc.net/problem/14499

문제 풀이

문제에서 핵심은 간단합니다.

map 칸이 0이면 주사위 아랫바닥 수가 map에 복사되고,

0이 아니면 map 칸이 주사위 아랫바닥에 복사되며, map 칸은 0이 됩니다.

다만 주의하셔야 할 문제점이 있는데,

주사위의 x, y 좌표가 주어진다고 하였으나,

사실 y,x 좌표가 주어진다는 겁니다.

세로 크기 N, 가로 크기 M (1 ≤ N, M ≤ 20), 주사위를 놓은 곳의 좌표 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1),

위를 보시면, x는 세로인 N / y는 가로인 M 에 영향을 받죠..

예시는 x,y가 같은 좌표만 주어졌기에, 잘 풀었지만 틀렸다면 대부분 여기서 틀리셨을 겁니다.

자 그러면 기본 동작을 짜는것은 어렵지 않기에, 주사위를 어떻게 굴려야 할지 알아보겠습니다.

맨 처음엔 각 주사위 눈금을 만들어 left,right,up,down 으로 연결시키려 하였지만

그렇게 하면 안됩니다.

(같은 의미로, x칸의 left는 y, 이런식으로도 하면 안됩니다. )

왜냐하면 주사위가 계속 굴러가기때문에, 동-서-남-북 방향으로 굴렀을떄의 값이 모두 다르기 때문입니다.

그럼 어떻게 해야하나?

주사위가 left, right, up, down 시 아에 배열값을 바꿔 줘 버립니다.

예를들면,

  1
4 2 3
  6
  5

이런 주사위가 있다고 생각 해 봅시다.

이 주사위를 왼쪽으로 굴린다면 위치가 바뀔텐데요,

이걸 다시

  1
4 2 3
  6
  5

로 만들어 줍니다.

여기서 주사위의 이동은 다음과 같습니다.

1->2 2->6 3(제자리) 4->1 5(제자리) 6->4

(해당 과정은 직접 그림 그리면서 해보시는게 가장 빠릅니다.)

이런식으로 1번값은 2번으로 옮기고, 2번값은 6번으로,

3,5번은 그대로 두고, 4번값은 1로, 6번값은 4번으로 옮기면

다시 원래순서에 맞게 주사위 배열이 될 겁니다.

즉, 언제나 밑에칸은 1번이고, 위에칸은 6번 이 되는겁니다.

이걸 각 방향별로 만들어 주시면 됩니다.

저는 편의를 위하여 DICE라는 클래스를 만들어서 클래스 안에서 처리 하도록 만들었습니다.

void left() {
		queue<int> q;
		for (int i = 0; i < 6; i++) {
			q.push(number[i]);
		}
		number[1] = q.front();
		q.pop();
		number[5] = q.front();
		q.pop();
		q.pop();
		number[0] = q.front();
		q.pop();
		q.pop();
		number[3] = q.front();
		q.pop();
		// 1->2 2->6 3 4->1 5 6->4
	}

주사위는 큐에 넣어서 돌렸습니다.

주의할 케이스

 N,M (1 ≤ N, M ≤ 20)
 x y(0 ≤ x ≤ N-1, 0 ≤ y ≤ M-1), 
 K (1 ≤ K ≤ 1,000)
 동쪽은 1, 서쪽은 2, 북쪽은 3, 남쪽은 4로 주어진다.
 지도 밖으로 나가려하면 무시한다. 

N,M 크기도 작고, k 갯수도 작기 때문에 시간초과나, 오버플로우가 발생할 일은 없습니다.

그럼 이제 주의해야할 건 최소값이죠.

N,M 이 1 이상이기에 (1,1) 지도가 생길 수 있습니다.

그러나 이건 아래의 지도 밖으로 나가려하면 무시한다

와 맞물려 고려 하지 않아도 됩니다.

또 한가지 주의할 점은, N,M 은 1 이상의 정수로 주어지지만,

x,y는 우리가 흔히 프로그래밍 할때 사용하는 0부터 시작하는 정수 라는 점만

주의 해 주시면 될 거 같습니다.

문제 코드

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

class DICE {

public:	
	void left() {
		queue<int> q;
		for (int i = 0; i < 6; i++) {
			q.push(number[i]);
		}
		number[1] = q.front();
		q.pop();
		number[5] = q.front();
		q.pop();
		q.pop();
		number[0] = q.front();
		q.pop();
		q.pop();
		number[3] = q.front();
		q.pop();
		// 1->2 2->6 3 4->1 5 6->4
	}
	void right() {
		queue<int> q;
		for (int i = 0; i < 6; i++) {
			q.push(number[i]);
		}
		number[3] = q.front();
		q.pop();
		number[0] = q.front();
		q.pop();
		q.pop();
		number[5] = q.front();
		q.pop();
		q.pop();
		number[1] = q.front();
		q.pop();
		// 1->4 2->1 3x 4->6 5 6->2
	}
	void up() {
		queue<int> q;
		for (int i = 0; i < 6; i++) {
			q.push(number[i]);
		}
		number[4] = q.front();
		q.pop();
		q.pop();
		number[0] = q.front();
		q.pop();
		q.pop();
		number[5] = q.front();
		q.pop();
		number[2] = q.front();
		q.pop();
		// 1->5 2 3->1 4 5->6 6->3
	}
	void down() {
		queue<int> q;
		for (int i = 0; i < 6; i++) {
			q.push(number[i]);
		}
		number[2] = q.front();
		q.pop();
		q.pop();
		number[5] = q.front();
		q.pop();
		q.pop();
		number[0] = q.front();
		q.pop();
		number[4] = q.front();
		// 1->3 2 3->6 4 5->1 6->5
	}
	int getDown() {
		return number[0];
	}
	void setDown(int a) {
		number[0] = a;
	}
	int getUp() {
		return number[5];
	}
	DICE() {
		for (int i = 0; i < 6; i++)
			number.push_back(0);
	}
private:
	vector<int> number;
	

};
int main() {
	int mapX, mapY, diceX, diceY, n;
	int temp;
	cin >> mapY >> mapX >> diceY >> diceX >> n;


	vector<vector<int>> map(mapY, vector<int>(mapX, 0));
	for (int i = 0; i < mapY; i++) {
		for (int j = 0; j < mapX; j++) {
			cin >> temp;
			map[i][j] = temp;
		}
	}
	DICE dice;
	for (int i = 0; i < n; i++) {
		int error = 0; 
		cin >> temp;
		switch(temp) {
		case 1:
			
			if (diceX == mapX - 1) {
				error = 1;
			}
			else {
				diceX++;
				dice.right();
			}
			break;
		case 2:
			
			if (diceX == 0) {
				error = 1;
			}
			else {
				dice.left();
				diceX--;
			}
			break;
		case 3:
			
			if (diceY == 0) {
				error = 1;
			}
			else {
				dice.up();
				diceY--;
			}
			break;
		case 4:
			if (diceY == mapY - 1) {
				error = 1;
			}
			else {
				dice.down();
				diceY++;
			}
			break;
		}
		if (error==0){
			cout << dice.getUp() << endl;
			if (map[diceY][diceX] == 0)
				map[diceY][diceX] = dice.getDown();
			else {
				dice.setDown(map[diceY][diceX]);
				map[diceY][diceX] = 0;
			}
			/*
			for (int i = 0; i < mapY; i++) {
				for (int j = 0; j < mapX; j++) {
					cout << map[i][j] << " ";
				}
				cout << endl;
			}*/
		}
	}

	return 0; 
}



백준C++simulation Share Tweet +1