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

BOJ 14499 : 주사위 굴리기 (삼성 SW TEST A형)

by 피로물든딸기 2021. 2. 15.
반응형

삼성 A형 전체 링크

 

www.acmicpc.net/workbook/view/1152 (A형 문제집)

 

www.acmicpc.net/problem/14499

 

 

4방향으로 명령어대로 움직이면 되는 시뮬레이션 문제이다.

 

아래와 같은 주사위의 모양이 되도록,

6면체를 가지는 구조체 DICE를 만들자.

typedef struct st
{
	          int up;
	int left; int top; int right;
	          int down;
	          int bottom;
}DICE;

DICE dice; /* map을 움직이는 dice는 전역으로 선언 */

최대한 그림과 비슷하게 모양을 만들어 두면, 디버깅할 때 편하다.

 

input 함수로 MAP과 command를 저장해두고, move 동/서/남/북을 만들자.

 

moveEast의 경우는 아래와 같다.

void moveEast()
{
	int tmp[6] = { dice.up, dice.left, dice.top, dice.right, dice.down, dice.bottom };
	
	dice.top = tmp[1];
	dice.right = tmp[2];
	dice.bottom = tmp[3];
	dice.left = tmp[5];
}

dice의 6방향이 왜 저렇게 바뀌는지는 실제로 그려보면 된다.

다른 방향 함수는 최종 코드를 참고하자.

 

move 함수 이후에는 실제로 움직이도록 dr, dc를 선언하자.

dr, dc는 동 = 1, 서 = 2, 북 = 3, 남 = 4 가 되도록 만들면 편하다.

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

 

마찬가지로 move 4종류 함수를 1, 2, 3, 4와 mapping이 되도록 포인터를 선언해두면 바로 함수를 호출할 수 있다.

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

void moveEast();
...

int main(void)
{
	input();

	MOVE[1] = moveEast;
	MOVE[2] = moveWest;
	MOVE[3] = moveNorth;
	MOVE[4] = moveSouth;
    
    ...
    
    return 0;
}

 

함수 포인터를 잘 모른다면 if else를 이용해서 move를 실행하자.

( if(cmd == 1) moveEast(); )

 

K개의 command를 실행해주면 되는데, 이때 주사위가 벽을 넘어서는지에 대한 경계조건을 추가하면 된다.

최종 코드는 아래와 같다.

#include <stdio.h>

#define MAX (20+5)

int N, M, X, Y, K;
int MAP[MAX][MAX];
int command[1000 + 50];

typedef struct st
{
	int up;
	int left; int top; int right;
	int down;
	int bottom;
}DICE;

DICE dice;

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

void moveEast()
{
	int tmp[6] = { dice.up, dice.left, dice.top, dice.right, dice.down, dice.bottom };
	
	dice.top = tmp[1];
	dice.right = tmp[2];
	dice.bottom = tmp[3];
	dice.left = tmp[5];
}

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

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

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

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

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

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

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

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

	for (int i = 0; i < K; i++) scanf("%d", &command[i]);

}

void output()
{
	for (int r = 0; r < N; r++)
	{
		for (int c = 0; c < M; c++)
			printf("%d ", MAP[r][c]);
		putchar('\n');
	}
	putchar('\n');
	for (int i = 0; i < K; i++) printf("%d ", command[i]);
	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.bottom);
	putchar('\n');
}

int dr[] = { 0, 0, 0, -1, 1 };
int dc[] = { 0, 1, -1, 0, 0 };

int main(void)
{
	input();

	MOVE[1] = moveEast;
	MOVE[2] = moveWest;
	MOVE[3] = moveNorth;
	MOVE[4] = moveSouth;

	for (int i = 0; i < K; i++)
	{
		int cmd = command[i];
		
        /* 바깥으로 나가게 되는 경우 */
		if (X + dr[cmd] < 0 || X + dr[cmd] > N - 1 
        	|| Y + dc[cmd] < 0 || Y + dc[cmd] > M - 1) continue;

		X = X + dr[cmd];
		Y = Y + dc[cmd];

		MOVE[cmd]();

		/* 이동한 칸이 0이면, 주사위의 바닥면의 수가 복사 */
		if (MAP[X][Y] == 0) MAP[X][Y] = dice.bottom;
		else /* 0이 아니면, 칸에 쓰여진 수가 바닥면으로 복사 */
		{
			dice.bottom = MAP[X][Y];
			MAP[X][Y] = 0;
		}

		printf("%d\n", dice.top);
	}

	return 0;
}

 

A형의 경우 tc가 여러 개이므로 실제 시험에서는 main 코드는 다음과 같은 형식을 따른다.

int main(void)
{
	int T;
	scanf("%d", &T);

	MOVE[1] = moveEast;
	MOVE[2] = moveWest;
	MOVE[3] = moveNorth;
	MOVE[4] = moveSouth;
    
	for (int tc = 1; tc <= T; tc++)
	{
    	input();
        for (int i = 0; i < K; i++)
        {
		    ...
        }
        
        printf("#%d %d\n", tc, dice.top);
	}
    
    return 0;
}
반응형

댓글