Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Life Engineering

[BOJ 17822] 원판 돌리기 (Java) 본문

Problem Solving

[BOJ 17822] 원판 돌리기 (Java)

흑개 2022. 2. 25. 16:40

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

 

17822번: 원판 돌리기

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

www.acmicpc.net

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main_BOJ_17822 {
	static int[] dr= {-1,1,0,0};
	static int[] dc= {0,0,-1,1};
	static int N, M, T;
	static int[][] map;
	static boolean[][] visited;
	public static void main(String[] args) throws IOException {
		int x, d, k;
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st=new StringTokenizer(br.readLine());
		N=Integer.parseInt(st.nextToken());
		M=Integer.parseInt(st.nextToken());
		T=Integer.parseInt(st.nextToken());
		map=new int[N+1][M+1];
		for (int i=1; i<=N; i++) {
			st=new StringTokenizer(br.readLine());
			for (int j=1; j<=M; j++) {
				map[i][j]=Integer.parseInt(st.nextToken());
			}
		}
		for (int i=0; i<T; i++) {
			st=new StringTokenizer(br.readLine());
			x=Integer.parseInt(st.nextToken());
			d=Integer.parseInt(st.nextToken());
			k=Integer.parseInt(st.nextToken());
			rotate(x,d,k);
			if (!search()) {
				calculate();
			}
		}
		int answer=0;
		for (int i=1; i<=N; i++) {
			for (int j = 1; j <= M; j++) {
				answer+=map[i][j];
			}
		}
		System.out.println(answer);
	}
	private static void calculate() {
		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++;
				}
			}
		}
		double 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;
				}
			}
		}
		
	}
	
	private static boolean search() {
		visited=new boolean[N+1][M+1];
		boolean flag=false;
		for (int i=1; i<=N; i++) {
			for (int j = 1; j <= M; j++) {
				if (!visited[i][j] && map[i][j]>0) {
					int val=map[i][j];
					if (dfs(i,j,val)) {
						flag=true;
					}
					else {		//인접한 거 발견 못했을 경우 다시 되돌려주기
						map[i][j]=val;
					}
				}
			}
		}
		return flag;
	}
	
	private static boolean dfs(int r, int c, int val) {
		boolean flag=false;
		visited[r][c]=true;
		map[r][c]=0;
		for (int i=0; i<4; i++) {
			int nr=r+dr[i];
			int nc=c+dc[i];
			if (nr<=0 || nr>N) continue;
			if (nc==0) nc+=M;
			else if (nc==M+1) nc-=M;
			if (!visited[nr][nc] && map[nr][nc]==val) {
				dfs(nr,nc,val);	//인접하면서 수가 같은 걸 하나라도 찾을 경우
				flag=true;
			}
		}
		return flag;
	}
	private static void rotate(int x, int d, int k) {
		for (int i=x; i<=N; i+=x) {
			int[] temp=new int[M+1];
			for (int j=1; j<=M; j++) {
				if (d==0) {
					int idx=j, cnt=0;
					while (cnt<k) {
						idx=(idx+1)%M;
						if (idx==0) idx=M;
						cnt++;
					}
					temp[idx]=map[i][j];	
				}
				else if (d==1) {
					int idx=j, cnt=0;
					while (cnt<k) {
						idx=(idx-1)%M;
						if (idx==0) idx=M;
						cnt++;
					}
					temp[idx]=map[i][j];
				}
			}
			map[i]=Arrays.copyOf(temp, M+1);
		}
	}

}

어떻게 회전 시킬까? 에 대한 부분이 까다로웠다. 인덱스를 1부터 시작해서 고민을 많이 했었는데..

다른 분들의 코드를 보니 원판의 번호를 나타내는 부분, 즉 행 부분은 1부터 시작하고(배수별로 움직이므로),

열 부분은 0부터 시작해서 애초에 혼란이 생길 수 있는 부분을 막아 주었다.

void rot(int lev, int many) {		//시계방향으로만 회전
	for (int k = 0; k < many; k++) {
		int temp = arr[lev][m - 1];
		for (int i = m-1; i > 0; i--) 
			arr[lev][i] = arr[lev][i - 1];		
		arr[lev][0] = temp;
	}
}

(출처: https://imnotabear.tistory.com/215 님)

 

-뒤에서부터 움직이면 따로 temp에 값 저장할 필요 X이다.

-반시계 방향으로 움직일 경우, k가 반시계 방향으로 움직인 경우= col-k만큼 시계방향으로 움직인 것과  일치하므로 k값만 조정해준다.

'Problem Solving' 카테고리의 다른 글

[프로그래머스] 삼각 달팽이 (Java)  (0) 2022.03.01
[BOJ 13305] 주유소 (Java)  (0) 2022.02.25
[BOJ 17143] 낚시왕 (Java)  (0) 2022.02.24
[BOJ 16236] 아기 상어 (Java)  (0) 2022.02.23
[BOJ 14499] 주사위 굴리기 (Java)  (0) 2022.02.23