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

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

접근

단순 구현 문제이다. N * N 배열 MAP 각 칸에 [ 파이어볼의 갯수, 짝수 방향에서 온 갯수, 홀수 방향에서 온 갯수, 총 질량, 총 속도, 방향 ] 을 저장하여 현재 상태를 저장하고, 각 칸을 순회하면서 다음 이동을 조건에 맞게 계산해주게 된다.

방향은 해당 칸에 파이어볼이 1개 있을 경우에만 의미가 있으며, 1개 이상 있을 경우 조건에 따라 다음 방향은 0,2,4,6 혹은 1,3,5,7이 되게 된다.

코드

#include<iostream>
#include<cstring>

using namespace std;

#define endl '\n'
#define MAX_N 51
#define MAX_M 2501

int N, M, K;
int MAP[MAX_N][MAX_N][6];  // [ total, even, odd, mass, speed, direction ]
int C_MAP[MAX_N][MAX_N][6];  // 이동 후의 상태를 임시로 저장하는 MAP과 동일한 배열

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


// 이동 후의 상태를 임시로 저장하는 C_MAP의 정보를 MAP으로 옮기고, C_MAP을 초기화
void CopyMap()
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            for (int k = 0; k < 6; k++)
            {
                MAP[i][j][k] = C_MAP[i][j][k];
            }
        }
    }
    memset(C_MAP, 0, sizeof(C_MAP));
}


void MoveFireballs()
{
    int nr, nc, m, s, d;
    for (int r = 0; r < N; r++)
    {
        for (int c = 0; c < N; c++)
        {
            if (MAP[r][c][0] == 0) continue;
            if (MAP[r][c][0] == 1)
            {
                // 현재 위치의 파이어볼의 수가 1개일 때
                s = MAP[r][c][4];
                d = MAP[r][c][5];
                nr = r + s * dr[d];
                nc = c + s * dc[d];
                nr %= N;
                nc %= N;
                if (nr < 0) nr += N;
                if (nc < 0) nc += N;

                // 다음 위치의 파이어볼 수++
                C_MAP[nr][nc][0]++;
                // 방향의 홀수/짝수에 따라 카운트수++
                if (d % 2 == 1)
                {
                    C_MAP[nr][nc][2]++;
                }
                else
                {
                    C_MAP[nr][nc][1]++;
                }
                // 다음 위치 파이어볼들의 질량 및 속도 합산
                C_MAP[nr][nc][3] += MAP[r][c][3];
                C_MAP[nr][nc][4] += s;
                C_MAP[nr][nc][5] = d;
            }
            else
            {
                // 현재 위치의 파이어볼 수가 여러개일 때
                m = MAP[r][c][3] / 5;
                if (m == 0) continue;  // 5로 나눈 질량이 0이라면 소멸
                s = MAP[r][c][4] / MAP[r][c][0];
                // 현재 칸에 모인 파이어볼들의 방향이 짝수방향 혹은 홀수방향으로 통일되었다면 0,2,4,8, 아니라면 1,3,5,7
                if (MAP[r][c][0] == MAP[r][c][1] || MAP[r][c][0] == MAP[r][c][2]) d = 0;
                else d = 1;
                while (d < 8)
                {
                    // 조건에 맞는 질량 및 속도, 방향으로 이동하도록 계산
                    nr = r + s * dr[d];
                    nc = c + s * dc[d];
                    nr %= N;
                    nc %= N;
                    if (nr < 0) nr += N;
                    if (nc < 0) nc += N;

                    C_MAP[nr][nc][0]++;
                    if (d % 2 == 1)
                    {
                        C_MAP[nr][nc][2]++;
                    }
                    else
                    {
                        C_MAP[nr][nc][1]++;
                    }
                    C_MAP[nr][nc][3] += m;
                    C_MAP[nr][nc][4] += s;
                    C_MAP[nr][nc][5] = d;
                    d += 2;
                }
            }
        }
    }
}


void PrintMass()
{
    int mass = 0;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (MAP[i][j][0] == 0) continue;
            if (MAP[i][j][0] == 1)
            {
                // 현재 칸에 파이어볼이 1개라면 질량을 합산
                mass += MAP[i][j][3];
            }
            else
            {
                // 현재 칸에 파이어볼이 여러개라면 조건에 따라 4개로 나뉜 뒤의 질량을 합산
                int tmp = MAP[i][j][3] / 5;
                mass += tmp * 4;
            }
        }
    }
    cout << mass << endl;
}


int main(int argc, char** argv)
{
    // freopen 주석 처리
    // freopen("input.txt", "r", stdin);

    cin >> N >> M >> K;
    for (int i = 0; i < M; i++)
    {
        int r, c, m, s, d;
        cin >> r >> c >> m >> s >> d;
        MAP[r - 1][c - 1][0] = 1;
        MAP[r - 1][c - 1][3] = m;
        MAP[r - 1][c - 1][4] = s;
        MAP[r - 1][c - 1][5] = d;
    }

    for (int i = 0; i < K; i++)
    {
        MoveFireballs();
        CopyMap();
    }

    PrintMass();

    return 0;
}

더 생각해 볼 것?

...

코드나 내용 관련 조언, 부족한 점 및 질문 언제든 환영합니다!

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기