공부공간

BOJ - 17822 ) 원판 돌리기 본문

알고리즘/구현,시뮬

BOJ - 17822 ) 원판 돌리기

개발자가될수있을까? 2020. 2. 19. 15:50


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

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀있고, i번째 원판에 적힌 j번째 수의 위치는 (i, j)로 표현한다. 수의 위치는 다음을 만족한다. (i, 1)은 (i, 2), (i, M)과 인접하다. (i, M)은 (i, M-1), (i, 1)과 인접하다. (i, j)는 (i, j-1), (i, j

www.acmicpc.net


N개의 층이 있는 원판을  M등분하여, 각층에 숫자를 넣고, K번의 회전연산을 통하여 답을 구하는 문제이다.

 

각 회전연산마다 이웃한것끼리 같은것이면 ( 인접하면 ) 그수는 제거할수있다.

 

만약 수를 제거할수 없는 상황에는 원판전체의 평균을 구하여 그 평균보다 크면 -1 , 작으면 +1 작업을 통하여

 

수를 바꾸어준다.

 

원판위에 숫자가 존재하기 때문에 Index의 맨 마지막과 첫번째는 인접하고, 

 

N번째 층은 N-1번째 층과 세로로 인접, 1번째 층은 2번째층과 세로로인접 나머지 K번째 층은

 

K+1, K-1층과 인접해있다.

 

문제를 풀기위해서, 원판위에 적힌 숫자를 배열로 옮기고, 각 배열이 원판처럼 연결되어있다고 생각해서 풀었다.

 

가로, 세로의 인접을 확인하기위해서 코드가 길어졌지만, 반복문을 통해서 줄일 수있었다.

 

내가 생각한 순서는

 

1. K의 단계를 2차원 배열로 저장한다. 첫번째 요소는 Rotate할 Row의 값, 두번째는 시계방향인지?반시계인지?

 

세번째는 몇번 연산을 수행하는지?

 

2. K에서 첫번째를 가져와 Rotate연산을 수행한다. 

 

3. 회전이 완료되면 이웃한 것 중에 인접한 것이 있는지 판단을 하고,

 

4.그러한 경우가 없을때에는 평균을 구해서 숫자를 변경해준다.

 

사실상 FOR문으로 풀수있었지만 상당히 신경써주어야할 부분이 많아서인지 정답률이 낮았던것 같다.


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	static int N,M,K;
	static int map[][];
	static int Rotate[][];
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		map = new int[N+1][M+1];
		for(int y = 1; y <=N ; y++) {
			st = new StringTokenizer(br.readLine());
			for(int x = 1; x<=M  ; x++) {
				map[y][x] = Integer.parseInt(st.nextToken());
			}
		}
		Rotate = new int[K+1][4];
		
		for(int y = 1 ; y<= K ; y++) {
			st = new StringTokenizer(br.readLine());
			Rotate[y][1] = Integer.parseInt(st.nextToken());   // xi 의 배수들이 대상으로
			Rotate[y][2] = Integer.parseInt(st.nextToken());   // 0 시계 1 반시계
			Rotate[y][3] = Integer.parseInt(st.nextToken());   // 횟수
		}
		for(int index = 1 ; index <= K ;index++) {
			int x = Rotate[index][1]; int rdir =Rotate[index][2]; int rtime = Rotate[index][3];
			for(int arr = x; arr <=N ; arr +=x ) {
				RotateClock(arr,rdir,rtime);
			}
			// 회전완료 인접한것 체크
			boolean adj = true;
			boolean visit[][] = new boolean[N+1][M+1];
			for(int i =1 ; i <=N ; i++) {
				for(int j= 1; j <=M ; j++) {
					if(map[i][j]==0) continue;
					
					if( i == 1){
						if(j ==1) {
							if(map[i][j]==map[i][j+1]) {
								visit[i][j] = true;
								visit[i][j+1] = true;
							}
							if(map[i][j]==map[i][M]) {
								visit[i][j] = true;
								visit[i][M] = true;
							}
							
						}
						else if( j == M) {
							if(map[i][j]==map[i][1]) {
								visit[i][j] = true;
								visit[i][1] = true;
							}
							 if(map[i][M-1]==map[i][M]) {
								visit[i][M-1] = true;
								visit[i][M] = true;
							}
						}
						else {
							if(map[i][j] == map[i][j-1]) {
								visit[i][j] = true;
								visit[i][j-1] = true;
							}
							if(map[i][j] == map[i][j+1]) {
								visit[i][j] = true;
								visit[i][j+1] = true;
							}
						} // row 체크
						
						// col 체크
						if(map[i][j] == map[i+1][j]) {
							visit[i][j] = true;
							visit[i+1][j] = true;
						}
					}
					else if( i == N) {
						if(j ==1) {
							if(map[i][j]==map[i][j+1]) {
								visit[i][j] = true;
								visit[i][j+1] = true;
							}
							if(map[i][j]==map[i][M]) {
								visit[i][j] = true;
								visit[i][M] = true;
							}
							
						}
						else if( j == M) {
							if(map[i][j]==map[i][1]) {
								visit[i][j] = true;
								visit[i][1] = true;
							}
							if(map[i][M-1]==map[i][M]) {
								visit[i][M-1] = true;
								visit[i][M] = true;
							}
						}
						else {
							if(map[i][j] == map[i][j-1]) {
								visit[i][j] = true;
								visit[i][j-1] = true;
							}
							if(map[i][j] == map[i][j+1]) {
								visit[i][j] = true;
								visit[i][j+1] = true;
							}
						}
						
						if(map[i][j] == map[i-1][j]) {
							visit[i][j] = true;
							visit[i-1][j] = true;
						}
						
					}
					else {
						if(j ==1) {
							if(map[i][j]==map[i][j+1]) {
								visit[i][j] = true;
								visit[i][j+1] = true;
							}
							if(map[i][j]==map[i][M]) {
								visit[i][j] = true;
								visit[i][M] = true;
							}
							
						}
						else if( j == M) {
							if(map[i][j]==map[i][1]) {
								visit[i][j] = true;
								visit[i][1] = true;
							}
							if(map[i][M-1]==map[i][M]) {
								visit[i][M-1] = true;
								visit[i][M] = true;
							}
						}
						else {
							if(map[i][j] == map[i][j-1]) {
								visit[i][j] = true;
								visit[i][j-1] = true;
							}
							if(map[i][j] == map[i][j+1]) {
								visit[i][j] = true;
								visit[i][j+1] = true;
							}
						}
						
						if(map[i][j] == map[i-1][j]) {
							visit[i][j] = true;
							visit[i-1][j] = true;
						}
						if(map[i][j] == map[i+1][j]) {
							visit[i][j] = true;
							visit[i+1][j] = true;
						}
					}
				}
			}
			
			for(int i =1 ; i <=N ; i++) {
				for(int j= 1; j <=M ; j++) {
					if(visit[i][j]) {
						map[i][j] =0;
						adj = false;
					} 
				}
			}
			
			if(adj) {
				// 평균을 구하고 큰건 -1 작은건 +1 ..
				double avg =0; int sum =0; int cnt =0;
				for(int i = 1 ; i <= N ; i ++) {
					for(int j = 1 ; j <= M ; j++) {
						if(map[i][j] !=0) {
							sum+= map[i][j]; cnt++;	
						}
					} 
				}
				
				avg = ((double)sum)/(cnt);
				
				for(int i = 1 ; i <= N ; i ++) {
					for(int j = 1 ; j <= M ; j++) {
						if(map[i][j]!=0) {
							if( map[i][j] > avg ) {
								map[i][j] -= 1;
							}
							else if( map[i][j] < avg ){
								map[i][j] +=1;
							}
						}
					} 
				}		
			}		
		}
		
		int res =0;
		for(int y =1 ; y <=N ; y++) {
			for(int x= 1; x <=M ; x++) {
				res += map[y][x];
			}
		}
		System.out.print(res);
	}
	public static void RotateClock(int Row, int dir , int time) {
		while(time > 0) {
			if(dir == 0) { // 시계방향
				int last = map[Row][M];
				for(int index = M; index >1; index--) {
					map[Row][index] = map[Row][index-1];
				}
				map[Row][1] = last;
			}
			
			else { // 반대
				int first = map[Row][1];
				for(int index = 1; index <M; index++) {
					map[Row][index] = map[Row][index+1];
				}
				map[Row][M] = first;
			}
			time--;
		}
	}
}

Comments