본문 바로가기
알고리즘/[ADV] 삼성 SW 역량 테스트 A형

[코드트리] 정육면체 한번 더 굴리기 (삼성 SW 역량테스트 2021 하반기 오전 1번)

by 피로물든딸기 2024. 6. 9.
반응형

 

SW 역량테스트 합격하기 A형 강의 오픈!! (인프런 바로가기)

 

삼성 A형 전체 링크

 

https://www.codetree.ai/training-field/frequent-problems/problems/cube-rounding-again

이후 설명 및 입/출력은 링크 참고

 

정육면체 한번 더 굴리기 문제 풀이BOJ 23288 : 주사위 굴리기 2와 비슷하지만,

입력과 초기 주사위 상태가 다르다.

 

이 문제는 N x N 격자판에서 주사위를 굴린다.

그리고 주사위의 초기 상태에서 2와 5의 위치가 반대다.

	dice.up = 5;
	dice.left = 4; dice.top = 1; dice.right = 3;
	dice.down = 2;
	dice.buttom = 6;

 

전체 코드는 다음과 같다.

#include <stdio.h>

#define MAX (20 + 5)

#define EAST (1)
#define WEST (2)
#define NORTH (3)
#define SOUTH (4)

int T;
int N, M;
int MAP[MAX][MAX];

typedef struct st1
{
	int up;
	int left; int top; int right;
	int down;
	int buttom;
}DICE;

DICE dice;

typedef struct st2
{
	int r;
	int c;
}RC;

RC queue[MAX * MAX];

void(*MOVE[6])(void);

/* 순서대로 0, 동, 서, 북, 남 */
int dr[] = { 0, 0, 0, -1, 1 };
int dc[] = { 0, 1, -1, 0, 0 };

int scoreBoard[MAX][MAX];

void moveEast()
{
	int tmp[6] = { dice.up, dice.left, dice.top, dice.right, dice.down, dice.buttom };

	dice.top = tmp[1];
	dice.right = tmp[2];
	dice.buttom = tmp[3];
	dice.left = tmp[5];
}

void moveWest()
{
	int tmp[6] = { dice.up, dice.left, dice.top, dice.right, dice.down, dice.buttom };

	dice.top = tmp[3];
	dice.right = tmp[5];
	dice.buttom = tmp[1];
	dice.left = tmp[2];
}

void moveNorth()
{
	int tmp[6] = { dice.up, dice.left, dice.top, dice.right, dice.down, dice.buttom };

	dice.up = tmp[2];
	dice.top = tmp[4];
	dice.down = tmp[5];
	dice.buttom = tmp[0];
}

void moveSouth()
{
	int tmp[6] = { dice.up, dice.left, dice.top, dice.right, dice.down, dice.buttom };

	dice.up = tmp[5];
	dice.top = tmp[0];
	dice.down = tmp[2];
	dice.buttom = tmp[4];
}

void input()
{
	scanf("%d %d", &N, &M);

	for (int r = 1; r <= N; r++)
		for (int c = 1; c <= N; c++)
			scoreBoard[r][c] = 0;

	for (int r = 1; r <= N; r++)
		for (int c = 1; c <= N; c++)
			scanf("%d", &MAP[r][c]);
}

void output()
{
	for (int r = 1; r <= N; r++)
	{
		for (int c = 1; c <= N; c++)
			printf("%d ", MAP[r][c]);
		putchar('\n');
	}
}

void outputDice()
{
	printf("  %d\n", dice.up);
	printf("%d %d %d\n", dice.left, dice.top, dice.right);
	printf("  %d\n", dice.down);
	printf("  %d\n", dice.buttom);
	putchar('\n');
}

int BFS(int r, int c)
{
	int wp, rp, number;
	int visit[MAX][MAX] = { 0 };

	wp = rp = 0;

	queue[wp].r = r;
	queue[wp++].c = c;

	visit[r][c] = 1;
	number = MAP[r][c];

	while (wp > rp)
	{
		RC out = queue[rp++];

		for (int i = 1; i <= 4; i++) // 4방향을 dr, dc의 1 ~ 4로 정의
		{
			int nr = out.r + dr[i];
			int nc = out.c + dc[i];

			if (nr <= 0 || nc <= 0 || nr > N || nc > N) continue;

			if (visit[nr][nc] == 0 && number == MAP[nr][nc])
			{
				queue[wp].r = nr;
				queue[wp++].c = nc;

				visit[nr][nc] = 1;
			}
		}
	}

	return wp * number; // (r, c)에 대한 점수 B * C 의 값
}

int main(void)
{
	int changeDir[5] = { 0 };
	int changeClock[5] = { 0 };
	int changeCounterClock[5] = { 0 };

	MOVE[EAST] = moveEast;
	MOVE[WEST] = moveWest;
	MOVE[NORTH] = moveNorth;
	MOVE[SOUTH] = moveSouth;

	changeDir[EAST] = WEST;
	changeDir[WEST] = EAST;
	changeDir[NORTH] = SOUTH;
	changeDir[SOUTH] = NORTH;

	changeClock[EAST] = SOUTH;
	changeClock[SOUTH] = WEST;
	changeClock[WEST] = NORTH;
	changeClock[NORTH] = EAST;

	changeCounterClock[EAST] = NORTH;
	changeCounterClock[NORTH] = WEST;
	changeCounterClock[WEST] = SOUTH;
	changeCounterClock[SOUTH] = EAST;

	// scanf("%d", &T);
	T = 1;
	for (int tc = 1; tc <= T; tc++)
	{
		int row, col, dir, score;

		input();

		for (int r = 1; r <= N; r++)
			for (int c = 1; c <= N; c++)
				scoreBoard[r][c] = BFS(r, c); // 미리 점수를 구한다.

		dice.up = 5;
		dice.left = 4; dice.top = 1; dice.right = 3;
		dice.down = 2;
		dice.buttom = 6;

		row = 1, col = 1, dir = EAST;
		score = 0;

		for (int i = 0; i < M; i++)
		{
			int nr, nc, A, B;

			nr = row + dr[dir];
			nc = col + dc[dir];

			if (nr <= 0 || nc <= 0 || nr > N || nc > N)
			{
				dir = changeDir[dir];
				nr = row + dr[dir];
				nc = col + dc[dir];
			}

			MOVE[dir]();

			score += scoreBoard[nr][nc];

			A = dice.buttom;
			B = MAP[nr][nc];

			if (A > B) dir = changeClock[dir];
			else if (A < B) dir = changeCounterClock[dir];
			// else { 변화 없음. }

			row = nr;
			col = nc;
		}

		printf("%d\n", score);
	}

	return 0;
}
반응형

댓글