ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 17811 (원판 돌리기)
    컴퓨터 공학 기초/알고리즘 (구현) 2020. 7. 31. 21:23

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

     

    17822번: 원판 돌리기

    반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀

    www.acmicpc.net

    해당 문제는 지문에 조건에 맞게 구현만 하면 되는 문제이다. 주의사항은 다음과 같다.

    1. 인접한 요소를 찾을 때 인접한 Y축 (세로) 의 값을 비교할 경우 -1 or n 과 같아지는 경우 비교를 하지 않게 예외처리

    2. 인접한 요소를 찾을 때 인접한 X축 (가로) 의 값을 비교할 경우 기준 X가 0 or m 과 같은 경우라면 X가 0일때는 기준 X축 배열의 가장 끝에 해당하는 요소와 비교를 수행하며 X가 m과 같은 경우에는 배열의 가장 첫 요소와 비교를 하여야 한다.

    3. 만약 인접한 요소가 하나도 없을경우 평균을 구하여 평균과 배열의 값을 비교하며 ++ or -- 를 해주게 되는데 여기서 평균 값은 실수자료형으로 구해야한다.

     

    풀이 :

    Map을 주어진 명령에 맞게 회전시키는 함수와, 배열의 모든 요소를 탐색하며 요소의 값이 0보다 클 경우 해당 요소와 인접한 경우의 모든 요소를 찾아서 0으로 바꾸어 준다. 이때 모든 요소를 찾을 때에는 BFS를 통하여 구현하였다.

     

    #include <iostream>
    #include <vector>
    #include <queue>
    using namespace std;
    
    struct Node{
    	int mapNum, dir, moveCnt;
    };
    struct Nodes{
    	int y, x;
    };
    
    Node nodeList[50];
    int checkY[4] = { 0, 0, -1, 1 };
    int checkX[4] = { -1, 1, 0, 0, };
    int n, m, t;
    int map[50][50];
    
    void spinMap(Node node){
    	// mapNum의 배수의 원판을 dir 방향으로 moveCnt 칸 만큼 민다
    	int i = 0;
    	int dir = node.dir;
    	int mCnt = node.moveCnt;
    
    	while (i < mCnt){
    		++i;
    		if (node.dir == 0){
    			// 시계
    			for (int y = node.mapNum; y <= n; y += node.mapNum){
    				int tmp = map[y - 1][m - 1];
    				for (int x = m - 1; x >= 1; --x){
    					map[y - 1][x] = map[y - 1][x - 1];
    				}
    				map[y - 1][0] = tmp;
    			}
    		}
    
    		else{
    			// 반 시계
    			for (int y = node.mapNum; y <= n; y += node.mapNum){
    				// 배수일 경우 밀기
    				int tmp = map[y - 1][0];
    				for (int x = 0; x < m - 1; ++x){
    					map[y - 1][x] = map[y - 1][x + 1];
    				}
    				map[y - 1][m - 1] = tmp;
    			}
    		}
    	}
    }
    
    // 배열의 요소 중 인접한 모든 값을 찾는 함수 
    bool bfs(int y, int x, int num){
    	int visit[50][50] = { 0 };
    	queue<Nodes> qu;
    
    	int flag = 0;
    	visit[y][x] = 1;
    
    	qu.push({y, x});
    	while (!qu.empty()){
    		Nodes now = qu.front();
    		for (int i = 0; i < 4; ++i){
    			int dy = now.y + checkY[i];
    			int dx = now.x + checkX[i];
    			// 기준 X 축이 0 일경우 해당 배열의 X 축 중 가장 마지막과 비교
    			if (now.x == 0 && i == 0) dx = m - 1;
    			// 기준 X 축이 해당 배열의 가장 마지막일 경우 해당 배열의 가장 첫 요소와 비교
    			if (now.x == m - 1 && i == 1) dx = 0;
    			if (dy < 0 || dx < 0 || dy >= n || dx >= m) continue;
    			if (visit[dy][dx] == 1) continue;
    			if (map[dy][dx] == num){
    				visit[dy][dx] = 1;
    				map[dy][dx] = 0;
    				qu.push({ dy, dx });
    				flag = 1;
    			}
    		}
    		qu.pop();
    	}
    	if (flag == 1) {
    		map[y][x] = 0;
    		return true;
    	}
    	else{
    		return false;
    	}
    
    
    }
    
    // 회전 시킨 뒤 0보다 큰 배열의 모든 요소를 가지고 BFS 수행 
    void checkList(){
    	int flag = 0;
    	int sum = 0, sumCnt = 0;
    	double to = 0;
    	for (int i = 0; i < n; ++i){
    		for (int j = 0; j < m; ++j){
    			if (map[i][j] <= 0) continue;
    			// 만약 BFS가 수행 되었을 때 즉 인접하게 겹치는 수가 있을 경우 flag = 1;
    			if (bfs(i, j, map[i][j]) == true) flag = 1;
    		}
    	}
    
    	// 배열의 요소중 아무것도 겹치는게 없을 경우 
    	if (flag == 0){
    		for (int i = 0; i < n; ++i){
    			for (int j = 0; j < m; ++j){
    				if (map[i][j] > 0) {
    					++sumCnt;
    					sum += map[i][j];
    				}
    			}
    		}
    		// 실수형으로 평균을 구한다.
    		to = (double(sum) / double(sumCnt));
    
    		for (int i = 0; i < n; ++i){
    			for (int j = 0; j < m; ++j){
    				if (map[i][j] > 0){
    					if (map[i][j] > to) map[i][j]--;
    					else if (map[i][j] < to) map[i][j]++;
    				}
    			}
    		}
    	}
    
    }
    
    
    int main(){
    	freopen_s(new FILE*, "tes.text", "r", stdin);
    	cin >> n >> m >> t;
    
    	for (int i = 0; i < n; ++i){
    		for (int j = 0; j < m; ++j){
    			cin >> map[i][j];
    		}
    	}
    
    	for (int i = 0; i < t; ++i){
    		int mapNum, dir, moveCnt;
    		cin >> mapNum >> dir >> moveCnt;
    		nodeList[i] = { mapNum, dir, moveCnt };
    	}
    
    	for (int i = 0; i < t; ++i){
    		spinMap(nodeList[i]);
    		checkList();
    	}
    	int sum = 0;
    
    	for (int i = 0; i < n; ++i){
    		for (int j = 0; j < m; ++j){
    			if (map[i][j] > 0) sum += map[i][j];
    		}
    	}
    	printf("%d", sum);
    
    }
    

    '컴퓨터 공학 기초 > 알고리즘 (구현)' 카테고리의 다른 글

    백준 11723 ( 집합 )  (0) 2020.08.20
    백준 17837 (새로운 게임 2)  (0) 2020.07.30
    백준 17140 (이차원 배열과 연산)  (0) 2020.07.28
    백준 17143 (낚시왕)  (0) 2020.07.27

    댓글

Designed by Tistory.