ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 21610 마법사 상어와 비바라기
    Algorithm/구현(Brute force, Back tracking, etc.) 2021. 12. 28. 22:49
    728x90

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

     

    21610번: 마법사 상어와 비바라기

    마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

    www.acmicpc.net

     

    - 상대적으로 쉬운 난이도의 구현 문제이다. 시간복잡도는 O(mN^2)이다. 

     

    - cloud_xy에 주어진 4 칸의 좌표를 담고, 총 m번의 이동을 시작한다. 

     

    1. 구름 이동의 경우, 1번 행(열)과 n번 행(열)이 연결되어 있는 점을 잘 고려해서 구현한다. 필자는 주어진 방향대로 한 칸씩 이동하도록 하되, 처음 s를 입력받을 때 s=s%n을 해 줌으로써 이동 횟수를 최소화해주었다.  이동할 때 마다 범위를 벗어나는지 체크를 하고(좌표가 0 미만, n이상인 경우) 수정을 해 주었다.

      또한 여기서, cloud가 해당 칸에 존재하는 여부를 담은 2차원 배열 cloud를 false로 초기화 해 주어야 한다. 그래야 다음 로직에서 겹치는 문제가 발생하지 않는다.

     

    2. 각 구름에서 비를 내리게 해서 구름이 있는 칸의 바구니에 저장된 물의 양이 1 증가하도록 한다.

     

    3. 구름이 사라지는 부분은 따로 구현하지 않는다.

     

    4. 물복사 버그를 진행한다. 대각선을 체크하되, 1번과 다르게 범위를 벗어나는 경우는 대각선으로 계산하지 않는다.

     

    5. 모든 칸을 순회하면서, 물의 양이 2 이상인 칸에 구름을 만든다. 이 때, 이전에 구름이 있던 곳은 pass한다.(cloud 배열 값 활용)

     

    - 이 문제는 1시간 내에는 풀어야 코딩테스트를 통과할 수 있을 것 같다!

    #include <iostream>
    #include <vector>
    using namespace std;
    int n, m;
    int map[50][50];
    bool cloud[50][50];
    vector<pair<int, int>> cloud_xy;
    vector<pair<int, int>> dir_move;
    int dx[] = { 0, -1, -1, -1, 0, 1, 1, 1 };
    int dy[] = { -1,-1,0,1,1,1,0,-1 };
    void debugging() {
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < n; j++) {
    			cout << map[i][j] << ' ';
    		}
    		cout << '\n';
    	}
    	cout << '\n';
    }
    int main() {
    	cin >> n >> m;
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < n; j++) {
    			cin >> map[i][j];
    		}
    	}
    	for (int i = 0; i < m; i++) {
    		int x, y;
    		cin >> x >> y;
    		dir_move.push_back({ x, y%n });
    	}
    	for (int i = n - 2; i < n; i++) {
    		for (int j = 0; j < 2; j++) {
    			cloud_xy.push_back({ i,j });
    		}
    	}
    	while (m--) {
    		int dir = dir_move[0].first-1; int move = dir_move[0].second;
    		dir_move.erase(dir_move.begin());
    		// 구름 이동
    		int now_cloud_size = cloud_xy.size();
    		for (int i = 0; i < now_cloud_size; i++) cloud[cloud_xy[i].first][cloud_xy[i].second] = false;
    		for (int i = 0; i < now_cloud_size; i++) {
    			int nx = cloud_xy[i].first;
    			int ny = cloud_xy[i].second;
    			for (int j = 0; j < move; j++) {
    				nx += dx[dir]; ny += dy[dir];
    				if (nx == -1) nx = n - 1; if (ny == -1) ny = n - 1;
    				if (nx == n) nx = 0; if (ny == n) ny = 0;
    			}
    			cloud_xy.push_back({ nx, ny });
    			map[nx][ny]++;
    			cloud[nx][ny] = true;
    		}
    		for (int i = 0; i < now_cloud_size; i++) cloud_xy.erase(cloud_xy.begin());
            // 물복사 버그
    		for (int i = 0; i < cloud_xy.size(); i++) {
    			int count = 0;
    			int now_x = cloud_xy[i].first; int now_y = cloud_xy[i].second;
    			for (int j = 1; j < 8; j+=2) {
    				int nx = now_x + dx[j]; int ny = now_y + dy[j];
    				if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
    				if (map[nx][ny]) count++;
    			}
    			map[now_x][now_y] += count;
    		}
            // 구름 생성 및 물의 양 -2
    		vector<pair<int, int>> temp_cloud;
    		for (int i = 0; i < cloud_xy.size(); i++) temp_cloud.push_back({ cloud_xy[i].first, cloud_xy[i].second });
    		cloud_xy.clear();
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < n; j++) {
    				if (!cloud[i][j] && map[i][j] >= 2) {
    					cloud_xy.push_back({ i,j });
    					cloud[i][j] = true;
    					map[i][j] -= 2;
    				}
    			}
    		}
    		for (int i = 0; i < temp_cloud.size(); i++) {
    			cloud[temp_cloud[i].first][temp_cloud[i].second] = false;
    		}
    	}
    	int answer = 0;
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < n; j++) {
    			answer += map[i][j];
    		}
    	}
    	cout << answer;
    	return 0;
    }

    댓글

Designed by Tistory.