191009 백준 알고리즘 문제풀기
09 Oct 2019 | baekjoon[14499] 주사위 굴리기
- 난이도: 하
- 시뮬레이션 문제로, 푸는데 총 1시간 반 소요됨.
- 문제 이해하는데 40분, 구현하는데 30분 미만, 디버깅에 30분 걸린 듯 하다.
- 어려운 문제는 아니였지만, 시뮬레이션의 조건을 잘못 파악하고 실수를 해서 40분이상을 날려먹었다.
- 조건을 하나 잘못 이해해서 시간을 많이 날려먹었다.
- 조건을 정확하게 파악하고 정리해두는것이 제일 중요한듯하다.
- 제일 관건이 되는것은 주사위를 굴리는것 정도로 매우 쉬운 난이도였다.
- 각각 주사위를 오른쪽, 왼쪽, 위, 아래로 굴릴 때의 case를 분류하고, 이에 맞게 동작하게 하면 됐다.
- 또한, 행/렬 실수로 시간을 또 날려먹었다.
- 제일 자주하고 반복되는 실수로.. 꼭 정확하게 파악하고 문제를 풀기 시작해야 한다.
- 이전에는 시뮬레이션 문제를 맞닥뜨리면 무조건 풀기 시작했다.
- 이럴 경우 결국 풀지 못하게 되는 경우도 많고 코드도 뒤죽박죽 되버린다….
- 어떤 문제건, 문제의 조건과 상황을 완벽하게 이해하고 풀기 시작해야 안정적으로 푸는것이 가능하다.
- 시뮬레이션 문제는 반드시
- 문제를 정확하게 이해하고
- 모든 조건을 정확하게 파악하고
- case를 정확하게 분리해서 푸는것이 중요함
- 시뮬레이션 문제로, 푸는데 총 1시간 반 소요됨.
- 문제
- https://www.acmicpc.net/problem/14499
- 크기가 NxM 맵에서 주사위 좌표가 순서대로 y,x 좌표로 주어질 때, 전체 맵에 바닥에 쓰이는 수 또한 입력된다.
- k번의 이동횟수와 이에 대한 주사위 회전 방향이 입력된다.
- k 번동안 주사위 맨 위의 숫자를 출력한다.
- 조건
- 주사위는 주어진 맵 안에서만 굴릴 수 있다.
- 주사위가 처음 놓이는 위치의 숫자는 무조건 0이다.
- 지도의 각 칸에는 정수가 하나씩 쓰여있다.
- 주사위는 동(1), 서(2), 북(3), 남(4) 방향으로 움직인다.
- 주사위를 굴렸을 때
- 이동한 칸에 쓰여 있는 수가 0이면 주사위 바닥면의 숫자가 칸으로 복사된다.
- 단, 주사위 숫자는 0이되는것이 아니라 유지된다!
- 이것을 오해해서 시간을 꽤 날려먹음..
- 이동한 칸에 숫자가 쓰여 있다면, 주사위 바닥면의 숫자가 칸의 숫자로 초기화되고 칸은 0이 된다.
- 이동한 칸에 쓰여 있는 수가 0이면 주사위 바닥면의 숫자가 칸으로 복사된다.
- 풀이
- 문제를 나눠보면
- 입력을 받아 맵과 명령어들을 저장한다.
- 전체 명령어동안
- 주사위를 굴린다.
- 주사위는 맵 안으로만 구를 수 있다.
- 맵 밖으로 넘어가면 그냥 넘어간다.
- 주사위가 굴러간 위치의 맵의 값에 따라 주사위와 값을 초기화한다.
- 맵에 값이 있다면 주사위 값을 초기화하고 맵을 비우고
- 맵에 값이 없다면 맵 값만 초기화한다.
- 현재 위치를 굴러간 위치로 초기화한다.
- 주사위는 십자가 모양으로 나열한 후, 순서대로 0부터 5까지 매핑한다.
- 이렇게 되면 주사위의 위쪽은 항상 인덱스 2가 된다.
- 값을 출력할땐 주사위의 2번 인덱스 값만 출력하면 됨
- 아래쪽은 항상 인덱스 5가 된다.
- 값을 초기화 할 댄 5번 인덱스 값만 초기화 하면 됨
- 이렇게 되면 주사위의 위쪽은 항상 인덱스 2가 된다.
- 문제를 나눠보면
#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int map[21][21]; // 주사위 맵
vector<int> order; // 명령어 저장용
int dx[] = { 0,1,-1,0,0 }; // 주사위 굴리기 방향
int dy[] = { 0,0,0,-1,1 };
int dice[] = { 0,0,0,0,0,0 }; // 주사위 값
void rotate_dice(int dir)
{
int t_dice[] = { 0,0,0,0,0,0 };
if (dir == 1)
{//오른쪽 회전
t_dice[0] = dice[0];
t_dice[1] = dice[5];
t_dice[2] = dice[1];
t_dice[3] = dice[2];
t_dice[4] = dice[4];
t_dice[5] = dice[3];
}
if (dir == 2)
{//왼쪽 회전
t_dice[0] = dice[0];
t_dice[1] = dice[2];
t_dice[2] = dice[3];
t_dice[3] = dice[5];
t_dice[4] = dice[4];
t_dice[5] = dice[1];
}
if (dir == 3)
{//위 회전
t_dice[0] = dice[2];
t_dice[1] = dice[1];
t_dice[2] = dice[4];
t_dice[3] = dice[3];
t_dice[4] = dice[5];
t_dice[5] = dice[0];
}
if (dir == 4)
{//아래 회전
t_dice[0] = dice[5];
t_dice[1] = dice[1];
t_dice[2] = dice[0];
t_dice[3] = dice[3];
t_dice[4] = dice[2];
t_dice[5] = dice[4];
}
for (int i = 0; i < 6; i++)
{ // 계산된 주사위를 원래 주사위로 초기화
dice[i] = t_dice[i];
}
}
int main()
{
int H, W, x, y, k;
scanf("%d %d %d %d %d", &H, &W, &y, &x, &k);
for (int j = 0; j < H; j++)
{
for (int i = 0; i < W; i++)
{
scanf("%d", &map[j][i]);
}
}
for (int i = 0; i < k; i++)
{
int t;
scanf("%d", &t);
order.push_back(t);
}
int cx = x; // 현재 위치를 받고
int cy = y;
for (int i = 0; i < k; i++)
{//전체 명령어 동안
int nx = cx + dx[order[i]]; // 다음 위치를 만든다음
int ny = cy + dy[order[i]];
//만약 범위 벗어나지 않는다면
if (0 <= nx && nx < W && 0 <= ny && ny < H)
{
//주사위 회전시키고
rotate_dice(order[i]);
//주사위 값 초기화와 맵 값 채우기
if (map[ny][nx] != 0)
{//만약 map에 값이 있다면
dice[5] = map[ny][nx]; // 주사위 값 초기화
map[ny][nx] = 0; // 맵을 비운다.
}
else
{//만약 map에 값이 없다면(0)
map[ny][nx] = dice[5]; // 맵 값을 초기화
}
printf("%d\n", dice[2]); // 주사위 위쪽 출력
cx = nx; // 다음 위치 초기화
cy = ny;
}
}
//std::system("pause");
return 0;
}