본문 바로가기
Algorithm/삼성 SW 역량 테스트 기출 문제

[Baekjoon][20056] 마법사 상어와 파이어볼

by 어발 2022. 6. 29.

출처 - 백준사이트

20056. 마법사 상어와 파이어볼

나의 풀이

해당 문제는 어렵지는 않으며, 몇가지만 고려하면 된다.

  1. 맵끼리 이어져 있다는 점.
  2. 방향이 모두 짝수이거나 홀수이면 나뉘어지는 파이어볼 방향이 0,2,4,6, 그렇지 않으면 1,3,5,7
    위 두사항만 잘 고려한다면 어렵지 않은 문제이다.
#include <iostream>
#include <vector>

#define MAX_SIZE    50

using namespace std;

const int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1};
const int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};

typedef struct _FireBall {
    int dir;
    int speed;
    int weight;

    _FireBall(int dir, int speed, int weight) : dir(dir), speed(speed), weight(weight) {}
} FireBall;

int N, M, K, ret;
vector<FireBall> map[MAX_SIZE][MAX_SIZE];

int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    cin >> N >> M >> K;

    for (int idx = 0 ; idx < M ; idx++) {
        int r, c, m, s, d;

        cin >> r >> c >> m >> s >> d;

        map[r-1][c-1].push_back(FireBall(d, s, m));
    }

    for (int idx = 0 ; idx < K ; idx++) {
        vector<FireBall> temp_map[MAX_SIZE][MAX_SIZE];

        // step 1. 파이어볼 이동
        for (int y = 0 ; y < N ; y++) {
            for (int x = 0 ; x < N ; x++) {
                while (!map[y][x].empty()) {
                    FireBall temp = map[y][x].back();
                    map[y][x].pop_back();

                    int ny = y + (dy[temp.dir] * temp.speed);
                    int nx = x + (dx[temp.dir] * temp.speed);

                    while (nx < 0)
                        nx += N;

                    while (nx >= N)
                        nx -= N;

                    while (ny < 0)
                        ny += N;

                    while (ny >= N)
                        ny -= N;

                    temp_map[ny][nx].push_back(temp);
                }
            }
        }

        // step 2. 파이어볼 합치기
        for (int y = 0 ; y < N ; y++) {
            for (int x = 0 ; x < N ; x++) {
                if (temp_map[y][x].size() > 1) {
                    int n_weight = temp_map[y][x][0].weight;
                    int n_speed = temp_map[y][x][0].speed;
                    int n_dir = temp_map[y][x][0].dir % 2;

                    int start_num = 0;
                    for (int t_idx = 1; t_idx < temp_map[y][x].size() ; t_idx++) {
                        n_weight += temp_map[y][x][t_idx].weight;
                        n_speed += temp_map[y][x][t_idx].speed;

                        if (n_dir != temp_map[y][x][t_idx].dir % 2)
                            start_num = 1;
                    }

                    // 질량이 0이 아닌경우, 0이면 소멸이니까 아무것도 하지 않음.
                    if (n_weight/5 != 0) {
                        // 방향이 모두 홀수거나 짝수인 경우는 n_dir = 0이므로, 0부터 2씩 커져가면서 방향설정하면되고 (0, 2, 4 , 6)
                        // 위의 경우가 아닌경우는 n_dir = 1이므로, 1부터 2씩 커져가면서 방향설정을 하면 되기에 start = n_dir로 설정한다. (1, 3, 5, 7)
                        for (int t_idx = 0 ; t_idx < 4 ; t_idx++) {
                            map[y][x].push_back(FireBall(start_num, n_speed/temp_map[y][x].size(), n_weight/5));
                            start_num += 2;
                        }
                    }
                }
                else if (temp_map[y][x].size() == 1)
                    map[y][x].push_back(temp_map[y][x].back());
            }
        }
    }

    for (int y = 0 ; y < N ; y++) {
        for (int x = 0 ; x < N ; x++) {
            while (!map[y][x].empty()) {
                ret += map[y][x].back().weight;
                map[y][x].pop_back();
            }
        }
    }

    cout << ret;

    return 0;
}
728x90

댓글