ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 20056번 - 마법사 상어와 파이어볼] C++ 풀이
    알고리즘/삼성SW역량테스트기출 2021. 10. 18. 12:44
    728x90
    반응형

    20056번.

     

    '1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결되어 있다'

    이 말인 즉슨, 1행에서 범위 초과하여 0행으로 갔을때, N행에 놓아주고, 1열에서 범위를 초과하여 0열로 갔을 때 N열에 놓아라는 의미이다. 반대로, N행에 있다가 범위를 초과하여 N + 1행으로 가면, 다시 1행에 놓아준다. 

     

    로직은 문제에 쓰인 그대로 풀이해주면 된다.

    나는 2차원 벡터에 파이어볼을 담고있는 큐를 담았다.

    그리고 이동한 파이어볼을 new_map 에 담아주고, 검사하면서 2개 이상 파이어볼이 있으면 합친 다음 4개로 만들어 주었다. 이 때, 만약 질량이 0이라면 파이어볼을 없애준다.

     

    k 번 이동 후에 남아있는 파이어볼 질량 총 합을 구해주면 된다.

     

    #include <stdio.h>
    #include <vector>
    #include <queue>
    
    #define MAX 51
    
    using namespace std;
    
    struct fireball {
    	int r;
    	int c;
    	int m; // 질량
    	int d; // 방향
    	int s; // 속력
    };
    
    int n, m, p;
    
    int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1};
    int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};
    
    int ans = 0;
    
    int main() {
    	scanf("%d %d %d", &n, &m, &p);
    	vector<vector<queue<fireball>>> map;
    	vector<vector<queue<fireball>>> new_map;
    
    	map.assign(n + 1, vector<queue<fireball>>(n + 1));
    	new_map.assign(n + 1, vector<queue<fireball>>(n + 1));
    
    	for(int i = 0; i < m; ++i) {
    		fireball tmp;
    		scanf("%d %d %d %d %d", &tmp.r, &tmp.c, &tmp.m, &tmp.s, &tmp.d);
    		map[tmp.r][tmp.c].push(tmp);
    	}
    
    	for(int i = 0; i < p; ++i) {
    		// 파이어볼 이동
    		for(int j = 1; j <= n; ++j) {
    			for(int k = 1; k <= n; ++k) {
    				if (!map[j][k].empty()) {
    					int size = map[j][k].size();
    					for(int v = 0; v < size; ++v) {
    						int x = map[j][k].front().r;
    						int y = map[j][k].front().c;
    						// d방향으로 s번 만큼 이동
    						for(int u = 0; u < map[j][k].front().s; ++u) {
    							x = x + dx[map[j][k].front().d];
    							y = y + dy[map[j][k].front().d];
    							if (x > n)
    								x = 1;
    							if (y > n)
    								y = 1;
    							if (x < 1)
    								x = n;
    							if (y < 1)
    								y = n;
    						}
    						fireball tmp = map[j][k].front();
    						tmp.r = x;
    						tmp.c = y;
    						new_map[x][y].push(tmp);
    						map[j][k].pop();
    					}
    				}
    			}
    		}
    
    		// 2개 이상의 파이어볼이 있는 칸이 있다면
    		for(int j = 1; j <= n; ++j) {
    			for(int k = 1; k <= n; ++k) {
    				if (new_map[j][k].size() == 1) {
    					map[j][k] = new_map[j][k];
    					new_map[j][k].pop();
    				} else if (new_map[j][k].size() >= 2) {
    					// 같은 칸의 파이어볼을 하나로 합친다
    					int m_sum = 0;
    					int s_sum = 0;
    					int size = new_map[j][k].size();
    					bool isAllEven = false;
    					bool isAllOdd = false;
    					while(!new_map[j][k].empty()) {
    						m_sum += new_map[j][k].front().m;
    						s_sum += new_map[j][k].front().s;
    						if (new_map[j][k].front().d % 2 == 0) {
    							isAllEven = true;
    						} else {
    							isAllOdd = true;
    						}
    						new_map[j][k].pop();
    					}
    					// 파이어볼은 4개의 파이어볼로 나눈다.
    					// 나누어진 파이어볼의 질량은 1/5
    					// 속력은 속력합 / 합쳐진 파이어볼 갯수
    					// 합쳐지는 파이어볼의 방향이 모두 홀수 or 모두 짝수면 0, 2, 4, 6 아니면 1, 3, 5, 7
    					if (isAllEven == isAllOdd && m_sum / 5 > 0) {
    						for(int u = 0; u < 4; ++u) {
    							fireball fb;
    							fb.r = j;
    							fb.c = k;
    							fb.s = s_sum / size;
    							fb.d = u * 2 + 1;
    							fb.m = m_sum / 5;
    							map[j][k].push(fb);
    						}
    					} else if (isAllEven != isAllOdd && m_sum / 5 > 0) {
    						for(int u = 0; u < 4; ++u) {
    							fireball fb;
    							fb.r = j;
    							fb.c = k;
    							fb.s = s_sum / size;
    							fb.d = u * 2;
    							fb.m = m_sum / 5;
    							map[j][k].push(fb);
    						}
    					}
    				}
    			}
    		}
    
    	}
    
    	for(int i = 1; i <= n; ++i) {
    		for(int j = 1; j <= n; ++j) {
    			if (map[i][j].size() > 0) {
    				while(!map[i][j].empty()) {
    					ans += map[i][j].front().m;
    					map[i][j].pop();
    				}
    			}
    		}
    	}
    
    	printf("%d\n", ans);
    }

     

    728x90

    댓글

Designed by Tistory.