백준(C, C++)/골드

백준 20056: 마법사 상어와 파이어볼 [C/C++], 삼성 코딩 테스트

치킨먹고싶어요 2022. 6. 12. 18:04

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

 

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

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

www.acmicpc.net

#include <iostream>
#include <vector>
#include <algorithm>
#define fastio() ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
int N, M, K, ans;
int dy[8= {-1-101110-1}; // 방향을 나타냅니다.
int dx[8= {01110-1-1-1};
struct Ball { // 공과 그 구성요소를 나타냅니다.
    int r, c, m, s, d;
};
vector<Ball> ball;
void input();
void move();
void solve();
 
int main() {
    fastio();
    input(); // 입력
    solve(); // 풀기
    return 0;
}
void input() { // 입력
    cin >> N >> M >> K;
    ball = vector<Ball>(M);
    for (int i = 0; i < M; i++cin >> ball[i].r >> ball[i].c >> ball[i].m >> ball[i].s >> ball[i].d;
}
void solve() { // 풀기
    while (K--) move(); // 옮기기
    for (int i = 0; i < ball.size(); i++) ans += ball[i].m; 
    cout << ans;
}
void move()  { // 옮기기
    vector<Ball> maps[55][55]; // 합쳐질 때를 대비해서 (같은 칸에 있는 파이어볼은 모두 하나로 합쳐진다.)
    for (int i = 0; i < ball.size(); i++) {
        Ball tmp;
        if (0 < ball[i].r + dy[ball[i].d] * ball[i].s) { // 1 이상 일때
            tmp.r = (ball[i].r + dy[ball[i].d] * ball[i].s) % N;
            if (tmp.r == 0) tmp.r = N; // 1부터 시작 하였으므로
        }
        else tmp.r = N + (ball[i].r + dy[ball[i].d] * ball[i].s) % N; // - 일때
        
        if (0 < ball[i].c + dx[ball[i].d] * ball[i].s) { // 1 이상 일때
            tmp.c = (ball[i].c + dx[ball[i].d] * ball[i].s) % N;
            if (tmp.c == 0) tmp.c = N; // 1부터 시작 하였으므로
        }
        else tmp.c = N + (ball[i].c + dx[ball[i].d] * ball[i].s) % N; // - 일때
        
        tmp.m = ball[i].m; tmp.s = ball[i].s; tmp.d = ball[i].d;
        maps[tmp.r][tmp.c].push_back(tmp); // 합쳐질 때를 대비해서
    }
    ball.clear(); // 중복 값을 처리하기 위하여 비운다
    
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= N; j++) {
            if (!maps[i][j].empty()) {
                if (maps[i][j].size() <= 1) ball.push_back(maps[i][j][0]); // 같은 칸이 아닐 때
                else { // 같은 칸에 있는 파이어볼은 모두 하나로 합쳐진다.
                    Ball tmp; tmp.r = i; tmp.c = j;
                    tmp.m = 0; tmp.s = 0; tmp.d = 0;
                    bool ways = true// 방향 체크
                    for (auto& iter: maps[i][j]) {
                        tmp.m += iter.m;
                        tmp.s += iter.s;
                        if (maps[i][j][0].d % 2 != iter.d % 2) ways = false// 합쳐지는 파이어볼의 방향이 모두 홀수이거나 모두 짝수이면, 방향은 0, 2, 4, 6이 되고, 그렇지 않으면 1, 3, 5, 7이 된다.
                    }
                    if (tmp.m < 5continue;  // 질량이 0인 파이어볼은 소멸되어 없어진다.
                    tmp.m = int(tmp.m / 5);
                    tmp.s = int(tmp.s / maps[i][j].size());
                    // 질량은 ⌊(합쳐진 파이어볼 질량의 합)/5⌋이다.
                    // 속력은 ⌊(합쳐진 파이어볼 속력의 합)/(합쳐진 파이어볼의 개수)⌋이다.
                    if (ways) {
                        for (int i = 0; i < 8; i += 2) {
                            tmp.d = i;
                            ball.push_back(tmp);
                        }
                    }
                    else {
                        for (int i = 1; i < 8; i += 2) {
                            tmp.d = i;
                            ball.push_back(tmp);
                        }
                    }
                }
            }
        }
    }
}
    
 
cs

풀이

간단한 시뮬레이션 문제입니다