알고리즘 문제/C++

[백준] 23288번: 주사위 굴리기 2 - C++

lingk 2022. 10. 6. 16:52

문제

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

 

23288번: 주사위 굴리기 2

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

www.acmicpc.net

 

설명

main 함수는 다음과 같다.

문제에서의 설명과 같이 다음과 같은 순서로 코드를 작성하였다. 이동 -> 점수 -> 방향결정

  1. 주사위가 이동 방향으로 한 칸 굴러간다. 만약, 이동 방향에 칸이 없다면, 이동 방향을 반대로 한 다음 한 칸 굴러간다.
  2. 주사위가 도착한 칸 (x, y)에 대한 점수를 획득한다.
  3. 주사위의 아랫면에 있는 정수 A와 주사위가 있는 칸 (x, y)에 있는 정수 B를 비교해 이동 방향을 결정한다.
    • A > B인 경우 이동 방향을 90도 시계 방향으로 회전시킨다.
    • A < B인 경우 이동 방향을 90도 반시계 방향으로 회전시킨다.
    • A = B인 경우 이동 방향에 변화는 없다.
int main()
{
    cin >> N >> M >> K;
    
    reset();
    for(int i = 1; i<= N; i++)
    {
        for(int j = 1; j<=M; j++)
        {
            cin >> map[i][j];
        }
    }
    
    x = 1; y = 1;
    moveDir = 0;
    
    for(int i = 0; i<K; i++)
    {
        // 이동
        //cout << "moveDir is: "<< moveDir << endl;
        //cout << "x: "<<x<<", y: "<<y<<endl;
        if((x+dir[moveDir][0] > N || x+dir[moveDir][0] < 1) || (y+dir[moveDir][1] > M || y+dir[moveDir][1] < 1))
        {
            if(moveDir < 2)
                moveDir+=2;
            else
                moveDir-=2;
            //cout << "change dir"<<endl;
        }
        
        moveDice(moveDir);
        x += dir[moveDir][0];
        y += dir[moveDir][1];
        
        // 점수
        B = map[x][y];
        C = 1;
        reset();
        DFS(x, y);
        //cout << B*C <<endl;
        result += B * C;
        
        // 다음 이동 방향
        A = dice[5];
        if(A>B)
        {
            if(moveDir != 3)
                moveDir += 1;
            else
                moveDir = 0;
        }
        if(A<B)
        {
            if(moveDir != 0)
                moveDir -= 1;
            else
                moveDir = 3;
        }
    }
    cout << result << '\n';
}

 

 

이동할때 사용한 함수는 다음과 같다. 주사위의 전개도를 dice라는 배열에 저장하여 굴리는 방향대로 위치를 바꿔주었다.

void moveDice(int dir)
{
    int tmp;
    if(dir == 0)
    {
        tmp = dice[3];
        dice[3] = dice[2];
        dice[2] = dice[1];
        dice[1] = dice[5];
        dice[5] = tmp;
    }
    else if(dir == 1)
    {
        tmp = dice[5];
        dice[5] = dice[4];
        dice[4] = dice[2];
        dice[2] = dice[0];
        dice[0] = tmp;
    }
    else if(dir == 2)
    {
        tmp = dice[1];
        dice[1] = dice[2];
        dice[2] = dice[3];
        dice[3] = dice[5];
        dice[5] = tmp;
    }
    else
    {
        tmp = dice[0];
        dice[0] = dice[2];
        dice[2] = dice[4];
        dice[4] = dice[5];
        dice[5] = tmp;
    }
}

 

점수를 계산할 때에는 DFS함수를 사용했다.

void DFS(int x, int y)
{
    visited[x][y] = true;
    for(int i = 0; i<4; i++)
    {
        int nx = x+dir[i][0];
        int ny = y+dir[i][1];
        if(( nx <= N && nx > 0) && (ny <= M && ny > 0))
        {
            if(map[nx][ny] == B && !visited[nx][ny])
            {
                visited[nx][ny] = 1;
                C += 1;
                DFS(nx, ny);
            }
        }
    }
}

 

 

 

전체 코드

#include <iostream>
#include <vector>

using namespace std;

int map[21][21];
bool visited[21][21];
int N, M, K;
int result = 0;
int x, y;
int dice[6] = {2,4,1,3,5,6};
int dir[4][2] ={{0,1}, {1,0}, {0,-1}, {-1,0}};
int moveDir;
int A,B,C;

void DFS(int x, int y);
void moveDice(int dir);
void reset();

int main()
{
    cin >> N >> M >> K;
    
    reset();
    for(int i = 1; i<= N; i++)
    {
        for(int j = 1; j<=M; j++)
        {
            cin >> map[i][j];
        }
    }
    
    x = 1; y = 1;
    moveDir = 0;
    
    for(int i = 0; i<K; i++)
    {
        // 이동
        if((x+dir[moveDir][0] > N || x+dir[moveDir][0] < 1) || (y+dir[moveDir][1] > M || y+dir[moveDir][1] < 1))
        {
            if(moveDir < 2)
                moveDir+=2;
            else
                moveDir-=2;
        }
        
        moveDice(moveDir);
        x += dir[moveDir][0];
        y += dir[moveDir][1];
        
        // 점수
        B = map[x][y];
        C = 1;
        reset();
        DFS(x, y);
        result += B * C;
        
        // 다음 이동 방향
        A = dice[5];
        if(A>B)
        {
            if(moveDir != 3)
                moveDir += 1;
            else
                moveDir = 0;
        }
        if(A<B)
        {
            if(moveDir != 0)
                moveDir -= 1;
            else
                moveDir = 3;
        }
    }
    cout << result << '\n';
}
void moveDice(int dir)
{
    int tmp;
    if(dir == 0)
    {
        tmp = dice[3];
        dice[3] = dice[2];
        dice[2] = dice[1];
        dice[1] = dice[5];
        dice[5] = tmp;
    }
    else if(dir == 1)
    {
        tmp = dice[5];
        dice[5] = dice[4];
        dice[4] = dice[2];
        dice[2] = dice[0];
        dice[0] = tmp;
    }
    else if(dir == 2)
    {
        tmp = dice[1];
        dice[1] = dice[2];
        dice[2] = dice[3];
        dice[3] = dice[5];
        dice[5] = tmp;
    }
    else
    {
        tmp = dice[0];
        dice[0] = dice[2];
        dice[2] = dice[4];
        dice[4] = dice[5];
        dice[5] = tmp;
    }
}

void reset()
{
    for(int i = 1; i<= N; i++)
    {
        for(int j = 1; j<= M; j++)
            visited[i][j] = false;
    }
}

void DFS(int x, int y)
{
    visited[x][y] = true;
    for(int i = 0; i<4; i++)
    {
        int nx = x+dir[i][0];
        int ny = y+dir[i][1];
        if(( nx <= N && nx > 0) && (ny <= M && ny > 0))
        {
            if(map[nx][ny] == B && !visited[nx][ny])
            {
                visited[nx][ny] = 1;
                C += 1;
                DFS(nx, ny);
            }
        }
    }
}
반응형