본문으로 바로가기

[구현] 주사위 굴리기 14499

category ps/구현 2021. 10. 4. 23:25

주사위 굴리기 14499

1. 가장 처음에 주사위는 모든 면에 0 이 적혀있다.

2. 지도의 칸에는 정수가 쓰여있는데, 주사위가 이동하여 도착한 칸이

2-1. 수가 0이면, 주사위의 바닥면의 수가 칸에 복사된다.

2-2. 수가 0이 아니면, 칸의 수가 주사위의 바닥면으로 복사된다. (그 후, 칸의 수는 0이 된다.)

구하는 것 : (x, y) 와 이동 명령이 있을 때, 이동 시 마다의 주사위 상단의 값을 출력한다.

주의사항 :

- 지도의 바깥은 안되며, 바깥으로 가는 명령은 무시. 출력 x

- 처음 시작점의 쓰인 수는 항상 0이다.

- 칸의 수는 0 또는 10 미만의 자연수이다.

 

틀렸던 풀이 코드

더보기
#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
using namespace std;
// 14499 주사위 굴리기

int n, m, x, y, k;

bool checkCoord(int x, int y){
	if(x >= 0 && x < n && y >= 0 && y < m) {
		return true;
	 }
	return false;
}

// flag 가 1이면 정방향 -1이면 역방향
void push(vector<int>& vec, int flag){
	if(flag == 1){
		int end = vec[vec.size() - 1];
		for(int i = 0; i < vec.size() - 1; i++){
			vec[i + 1] = vec[i];
		}
		vec[0] = end;
		return;
	}
	else{
		int start = vec[0];
		for(int i = 0; i < vec.size() - 1; i++){
			vec[i] = vec[i + 1];
		}
		vec[vec.size() - 1] = start;
	}
}

int main(){
	// 
	cin >> n >> m >> x >> y >> k;
	
	vector<vector<int>> board(n, vector<int>(m, 0));
	vector<int> orders(k, 0);

	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			cin >> board[i][j];
		}
	}
	for(int i = 0; i < k; i++)
		cin >> orders[i];
	
	vector<int> diceRow(3, 0);
	vector<int> diceColumn(4, 0);
	// 주사위 맨 윗 면은 diceRow[1] = diceColumn[1]
	// 주사위 맨 뒷 면은 diceColumn[3]
	vector<int>& upDown = {diceRow[0], diceRow[1], diceRow[2], diceColumn[3]};
	int upperBound = 3;
	int lowerBound = 2;
	int currentX = x;
	int currentY = y;
	
	for(int order : orders){
		// 동쪽
		if(order == 1){
			currentX = currentX;
			currentY = currentY + 1;
			if(!checkCoord(currentX, currentY)) continue;
			push(diceRow, -1);
			
			diceColumn[1] = diceRow[1];
			
			upperBound = ( upperBound + 1 ) % 4;
			lowerBound = ( lowerBound + 1 ) % 4; 
		}
		
		// 서쪽
		else if(order == 2){
			currentX = currentX;
			currentY = currentY - 1;
			if(!checkCoord(currentX, currentY)) continue;
			push(diceRow, 1);
			diceColumn[1] = diceRow[1];

		}
		
		// 남쪽
		else if(order == 4){
			currentX = currentX + 1;
			currentY = currentY;
			if(!checkCoord(currentX, currentY)) continue;
			push(diceColumn, -1);
			diceRow[1] = diceColumn[1];

		}
		
		// 북쪽
		else if(order == 3){
			currentX = currentX - 1;
			currentY = currentY;
			if(!checkCoord(currentX, currentY)) continue;
			push(diceColumn, 1);
			diceRow[1] = diceColumn[1];

		}
		
		if(board[currentX][currentY] == 0){
				board[currentX][currentY] = upDown[lowerBound];
			}
		else{
				upDown[lowerBound] = board[currentX][currentY];
				board[currentX][currentY] = 0;
				
		}
		cout << diceColumn[1] << '\n';
	}
	
}

- 동 / 서 로 이동할 때는 단면도의 row 방향만 바뀌고 북 / 남으로 이동할 때는 단면도의 column 방향만 바뀌는 것으로 잘못 생각하여 구현한 코드이다.

문제는 결국, 처음 노트에서 시작된다. 검증없이 추상적인 아이디어로만 코드 구현에 돌입하면 이와 같은 돌이킬 수 없는 실수가 발생한다. 이런 실수는 갈아엎는 수 밖에는 고칠 수 없으니, 처음 문제를 접근할 때 가장, 신중해야 한다.

풀이 코드

#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
using namespace std;
// 14499 주사위 굴리기

int n, m, x, y, k;

bool checkCoord(int x, int y){
	if(x >= 0 && x < n && y >= 0 && y < m) {
		return true;
	 }
	return false;
}

int main(){
	// 
	cin >> n >> m >> x >> y >> k;
	
	vector<vector<int>> board(n, vector<int>(m, 0));
	vector<int> orders(k, 0);

	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			cin >> board[i][j];
		}
	}
	for(int i = 0; i < k; i++)
		cin >> orders[i];
	
	int currentX = x;
	int currentY = y;
	
	vector<int> dice(7, 0);
	
	for(int order : orders){
		
		int nextX, nextY;
		
		// 동쪽
		if(order == 1){
			nextX = currentX;
			nextY = currentY + 1;
			if(!checkCoord(nextX, nextY)) continue;

			int temp = dice[1];
            dice[1] = dice[4];
            dice[4] = dice[6];
            dice[6] = dice[3];
            dice[3] = temp;
			
		}
		
		// 서쪽
		else if(order == 2){
			nextX = currentX;
			nextY = currentY - 1;
			if(!checkCoord(nextX, nextY)) continue;
			int temp = dice[1];
            dice[1] = dice[3];
            dice[3] = dice[6];
            dice[6] = dice[4];
            dice[4] = temp;

		}
		
		// 남쪽
		else if(order == 4){
			nextX = currentX + 1;
			nextY = currentY;
			if(!checkCoord(nextX, nextY)) continue;
			int temp = dice[1];
            dice[1] = dice[2];
            dice[2] = dice[6];
            dice[6] = dice[5];
            dice[5] = temp;

		}
		
		// 북쪽
		else if(order == 3){
			nextX = currentX - 1;
			nextY = currentY;
			if(!checkCoord(nextX, nextY)) continue;
			int temp = dice[1];
            dice[1] = dice[5];
            dice[5] = dice[6];
            dice[6] = dice[2];
            dice[2] = temp;

		}
		
		if(board[nextX][nextY] == 0){
				board[nextX][nextY] = dice[6];
			}
		else{
				dice[6] = board[nextX][nextY];
				board[nextX][nextY] = 0;
				
		}
		cout << dice[1] << '\n';
		currentY = nextY;
		currentX = nextX;
	}
	
}

 

해설


적용한 레시피 / 방법론 + 접근법

풀이

1. 주사위의 정보를 어떻게 저장할 것인가.

- 면에 번호를 메긴다.

2. 동 / 서 / 북 / 남에 대해서 주사위의 정보가 어떻게 변화하는가.

- 모든 경우에 대해서 어떻게 변하는지 직접 생각해서 식을 만들어낸다. 

아쉬웠던 부분 / 오답 원인 / 개선해야 할 점

1. 주사위가 움직일 때의 주사위의 정보의 변화를 "이렇지 않을까?" 라는 생각만을 가지고 코드 구현에 돌입한 점.

- 맨 위의 코드는, 동 / 서 로 이동할 때는 단면도의 row 방향만 바뀌고 북 / 남으로 이동할 때는 단면도의 column 방향만 바뀌는 것으로 잘못 생각하여 구현한 코드이다.

문제는 결국, 처음 노트에서 시작된다. 검증없이 추상적인 아이디어로만 코드 구현에 돌입하면 이와 같은 돌이킬 수 없는 실수가 발생한다. 이런 실수는 갈아엎는 수 밖에는 고칠 수 없으니, 처음 문제를 접근할 때 가장, 신중해야 한다.

 

반응형