티스토리 뷰

문제설명은 더보기를 눌러주세요

더보기

문제

어른 상어가 마법사가 되었고, 파이어볼을 배웠다.

마법사 상어가 크기가 N×N인 격자에 파이어볼 M개를 발사했다. 가장 처음에 파이어볼은 각자 위치에서 이동을 대기하고 있다. i번 파이어볼의 위치는 (ri, ci), 질량은 mi이고, 방향은 di, 속력은 si이다. 위치 (r, c)는 r행 c열을 의미한다.

격자의 행과 열은 1번부터 N번까지 번호가 매겨져 있고, 1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결되어 있다.

행성의 방향은 어떤 칸과 인접한 8개의 칸의 방향을 의미하며, 정수로는 다음과 같다.

7 0 1
6   2
5 4 3

마법사 상어가 모든 파이어볼에게 이동을 명령하면 다음이 일들이 일어난다.

  1. 모든 파이어볼이 자신의 방향 di로 속력 si칸 만큼 이동한다.
    • 이동하는 중에는 같은 칸에 여러 개의 파이어볼이 있을 수도 있다.
  2. 이동이 모두 끝난 뒤, 2개 이상의 파이어볼이 있는 칸에서는 다음과 같은 일이 일어난다.
    1. 같은 칸에 있는 파이어볼은 모두 하나로 합쳐진다.
    2. 파이어볼은 4개의 파이어볼로 나누어진다.
    3. 나누어진 파이어볼의 질량, 속력, 방향은 다음과 같다.
      1. 질량은 ⌊(합쳐진 파이어볼 질량의 합)/5⌋이다.
      2. 속력은 ⌊(합쳐진 파이어볼 속력의 합)/(합쳐진 파이어볼의 개수)⌋이다.
      3. 합쳐지는 파이어볼의 방향이 모두 홀수이거나 모두 짝수이면, 방향은 0, 2, 4, 6이 되고,
        그렇지 않으면 1, 3, 5, 7이 된다.
    4. 질량이 0인 파이어볼은 소멸되어 없어진다.

마법사 상어가 이동을 K번 명령한 후, 남아있는 파이어볼 질량의 합을 구해보자.

입력

첫째 줄에 N, M, K가 주어진다.

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

서로 다른 두 파이어볼의 위치가 같은 경우는 입력으로 주어지지 않는다.

출력

마법사 상어가 이동을 K번 명령한 후, 남아있는 파이어볼 질량의 합을 출력한다.

제한

  • 4 ≤ N ≤ 50
  • 0 ≤ M ≤ N2
  • 1 ≤ K ≤ 1,000
  • 1 ≤ ri, ci ≤ N
  • 1 ≤ mi ≤ 1,000
  • 1 ≤ si ≤ 1,000
  • 0 ≤ di ≤ 7

 

-풀이-

1. 하나만 주의하자. 다음위치 = 현재위치 + 방향*속력으로 구한 분들이 많을텐데, 
   속력이 (맵의 크기 x2)를 넘어가면, 파이어볼이 맵 내에 존재할 수 있게끔 계속해서 맵의 위치만큼 더하거나 빼줘야한다.
   이 부분만 주의한다면 나머지는 쉽게 구현할 수 있다.

2. 사용한 구조체
    파이어볼을 저장할 파이어볼 구조체(fireball)
    존재하는 파이어볼들을 저장할 파이어볼 벡터(fireballs).
    존재하는 파이어볼들을 이동시킨 후 표시할 2차원 파이어볼 벡터(map)

3. 구현방법
    1) 파이어볼 이동 : 파이어볼 벡터를 돌며 현재위치 + 해당 파이어볼의 방향*속력으로 다음 위치를 구한다. 
    2) 구한 다음위치(x, y라 하겠음)에 해당 파이어볼을 push한다. (map[x][y].push_back)
    3) 맵을 돌면서 파이어볼이 2개 이상인 경우 파이어볼을 나눈 후 나눈 파이어볼들을 tmp벡터에 넣어주고,
        1개일 경우는 그대로 tmp벡터에 넣어준다.
    4) fireballs 벡터를 tmp벡터로 교체한다.

자세한 사항은 주석을 참고해주세요!

-코드-

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct fireball{
    int x;
    int y;
    int mass;
    int s;
    int d;
};
vector<fireball> map[51][51];
vector<fireball> fireballs;
bool isDir(int x, int y);
void split();
void move();
int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};
int N, M, K;

int main(){
    cin >> N >> M >> K;
    int x, y, mass, d, s, ans=0;
    for(int i=1; i<=M; i++){
        cin >> x >> y >> mass >> s >> d;
        fireballs.push_back({x, y, mass, s, d});
    }
    for(int i=1; i<=K; i++){
        move();
        split();
    }
    for(int i=0; i<fireballs.size(); i++) ans += fireballs[i].mass;
    cout << ans;
}

void move(){ // 파이어볼 이동
    for(int i=1; i<=N; i++){
        for(int j=1; j<=N; j++){
            map[i][j].clear();
        }
    }

    for(int i=0; i<fireballs.size(); i++){
        fireball cur = fireballs[i];
        int cx = cur.x, cy = cur.y;
        int nx = cx+dx[cur.d]*cur.s, ny = cy+dy[cur.d]*cur.s;
        while(nx < 1) nx += N; // 주의!! if문 만으로는 안된다
        while(ny < 1) ny += N;
        while(nx > N) nx -= N;
        while(ny > N) ny -= N;
        map[nx][ny].push_back({nx, ny, cur.mass, cur.s, cur.d});
    }
    return;
}

void split(){
    vector<fireball> temp;
    for(int i=1; i<=N; i++){
        for(int j=1; j<=N; j++){
            int massSum=0, sSum=0;
            if(map[i][j].size() == 0) continue;
            if(map[i][j].size() == 1) temp.push_back(map[i][j][0]); // 1개면 그대로 넣어준다.
            else { // 2개 이상일 경우 쪼갠다. 
                for(int k=0; k<map[i][j].size(); k++) {
                    massSum += map[i][j][k].mass;
                    sSum += map[i][j][k].s;
                }
                int nMass = massSum / 5;
                int nS = sSum / map[i][j].size();
                if(nMass == 0) continue;    
                if(isDir(i, j)) {
                    temp.push_back({i, j, nMass, nS, 0});
                    temp.push_back({i, j, nMass, nS, 2});
                    temp.push_back({i, j, nMass, nS, 4});
                    temp.push_back({i, j, nMass, nS, 6});
                } else {
                    temp.push_back({i, j, nMass, nS, 1});
                    temp.push_back({i, j, nMass, nS, 3});
                    temp.push_back({i, j, nMass, nS, 5});
                    temp.push_back({i, j, nMass, nS, 7});
                }
            }
        }
    }
    fireballs = temp; //fireballs 벡터를 tmp벡터로 교체한다.
}

bool isDir(int x, int y){ // 방향이 모두 홀수인지, 모두 짝수인지 판별하는 함수
    bool evenFlag=false, oddFlag=false;
    for(int i=0; i<map[x][y].size(); i++){
        if(map[x][y][i].d % 2) oddFlag = true;
        else evenFlag = true;
    }
    if(evenFlag && !oddFlag) return true;
    else if(!evenFlag && oddFlag) return true;
    else return false;
}
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday