알고리즘/삼성 기출

[백준/C++] 23288번 주사위 굴리기2 - 삼성SW기출

수디sudy 2022. 4. 6. 17:11

문제 : https://www.acmicpc.net/problem/23288

 

23288번: 주사위 굴리기 2

크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다. 가장 왼

www.acmicpc.net

 

 

 

 

[ 시뮬레이션 + BFS ]

이번 문제 또한 아주 친절하게 문제가 설명하는대로만 짜면 되는 문제이다..

그런데 주사위 방향을 어떻게 매번 돌릴지...? 를 너무 오랫동안 고민했다 🤣

int dice[7] = { 0,1,2,3,4,5,6 };

int d1 = dice[1];
	int d2 = dice[2];
	int d3 = dice[3];
	int d4 = dice[4];
	int d5 = dice[5];
	int d6 = dice[6];

	if (d == 0)
	{
		dice[1] = d4;
		dice[2] = d2;
		dice[3] = d1;
		dice[4] = d6;
		dice[5] = d5;
		dice[6] = d3;
	}
	else if (d == 1)
	{
		dice[1] = d3;
		dice[2] = d2;
		dice[3] = d6;
		dice[4] = d1;
		dice[5] = d5;
		dice[6] = d4;
	}
	else if (d == 2)
	{
		dice[1] = d2;
		dice[2] = d6;
		dice[3] = d3;
		dice[4] = d4;
		dice[5] = d1;
		dice[6] = d5;
	}
	else
	{
		dice[1] = d5;
		dice[2] = d1;
		dice[3] = d3;
		dice[4] = d4;
		dice[5] = d6;
		dice[6] = d2;
	}

그래서 위에처럼 각각 index

1 : 윗면

2 : 뒷면

3 : 오른쪽면

4 : 왼쪽면

5 : 앞면

6 : 아랫면

으로 배열을 만들어서 저장했고, 방향이 바뀔때마다 위에처럼 if문을 써서 각각 인덱스를 바꿔줬다.

 

이 부분 말고는 크게 어려운 부분은 없는듯 하다.

점수획득 부분도 다른 문제 유형과 같이 BFS로 인접한 칸을 찾아주면 된다 :)

 

 

*memset 쓸 때 꼭 memory.h include 해주기.. 안하면 백준에선 컴파일에러남.......🤣

(실제로 삼성 코테에서도 에러 나는지 궁금...)

 

 

 

<전체코드>

#include <iostream>
#include <queue>
#include <memory.h>
using namespace std;

int N, M, K;
const int MAX = 21;
int map[MAX][MAX];
bool visit[MAX][MAX];


int dice[7] = { 0,1,2,3,4,5,6 };

//이동 방향 : 동 서 남 북
int dy[4] = { 0,0,1,-1 };
int dx[4] = { 1,-1,0,0 };

int y = 1;
int x = 1;

//주사위 방향
int d = 0;

int score = 0;

int iter;

void roll_dice()
{
	//주사위가 이동 방향으로 한 칸 굴러간다. 만약, 이동 방향에 칸이 없다면, 이동 방향을 반대로 한 다음 한 칸 굴러간다.
	int ny = y + dy[d];
	int nx = x + dx[d];

	if (ny < 1 || nx < 1 || ny > N || nx > M)
	{
		if (d == 0)
			d = 1;
		else if (d == 1)
			d = 0;
		else if (d == 2)
			d = 3;
		else 
			d = 2;

		ny = y + dy[d];
		nx = x + dx[d];
	}

	y = ny;
	x = nx;
}

void get_score(int y, int x)
{
	//주사위가 도착한 칸 (x, y)에 대한 점수를 획득한다.
	//칸 (x, y)에 대한 점수는 다음과 같이 구할 수 있다. (x, y)에 있는 정수를 B라고 했을때, (x, y)에서 동서남북 방향으로 연속해서 이동할 수 있는 칸의 수 C를 모두 구한다. 
	//이때 이동할 수 있는 칸에는 모두 정수 B가 있어야 한다. 여기서 점수는 B와 C를 곱한 값이다.

	int cnt = 1;
	int s = map[y][x];

	//bool visit[MAX][MAX] = { false, };
	memset(visit, false, sizeof(visit));

	queue<pair<int, int>> q;

	q.push(make_pair(y, x));
	visit[y][x] = true;
	
	while (!q.empty())
	{
		y = q.front().first;
		x = q.front().second;
		q.pop();

		for (int dir = 0; dir < 4; dir++)
		{
			int ny = y + dy[dir];
			int nx = x + dx[dir];

			if (ny < 1 || nx < 1 || ny > N || nx > M)	continue;

			if (s == map[ny][nx] && !visit[ny][nx])
			{
				cnt++;
				q.push(make_pair(ny, nx));
				visit[ny][nx] = true;
			}
		}
	}
	

	score += (s * cnt);

}

void decision_direction(int d)
{

	int d1 = dice[1];
	int d2 = dice[2];
	int d3 = dice[3];
	int d4 = dice[4];
	int d5 = dice[5];
	int d6 = dice[6];

	if (d == 0)
	{
		dice[1] = d4;
		dice[2] = d2;
		dice[3] = d1;
		dice[4] = d6;
		dice[5] = d5;
		dice[6] = d3;
	}
	else if (d == 1)
	{
		dice[1] = d3;
		dice[2] = d2;
		dice[3] = d6;
		dice[4] = d1;
		dice[5] = d5;
		dice[6] = d4;
	}
	else if (d == 2)
	{
		dice[1] = d2;
		dice[2] = d6;
		dice[3] = d3;
		dice[4] = d4;
		dice[5] = d1;
		dice[6] = d5;
	}
	else
	{
		dice[1] = d5;
		dice[2] = d1;
		dice[3] = d3;
		dice[4] = d4;
		dice[5] = d6;
		dice[6] = d2;
	}
}

void change_direction()
{
	//주사위의 아랫면에 있는 정수 A와 주사위가 있는 칸 (x, y)에 있는 정수 B를 비교해 이동 방향을 결정한다
	//A > B인 경우 이동 방향을 90도 시계 방향으로 회전시킨다.
	//A < B인 경우 이동 방향을 90도 반시계 방향으로 회전시킨다.
	//A = B인 경우 이동 방향에 변화는 없다.

	if (dice[6] > map[y][x])
	{
		if (d == 0)
			d = 2;
		else if (d == 1)
			d = 3;
		else if (d == 2)
			d = 1;
		else
			d = 0;
	}
	else if (dice[6] < map[y][x])
	{
		if (d == 0)
			d = 3;
		else if (d == 1)
			d = 2;
		else if (d == 2)
			d = 0;
		else
			d = 1;
	}
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> N >> M >> K;

	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= M; x++)
		{
			cin >> map[y][x];
		}
	}


	for (iter = 0; iter < K; iter++)
	{
		roll_dice();
		decision_direction(d);
		change_direction();
		get_score(y, x);
	}

	cout << score << "\n";

	return 0;
}