본문 바로가기

알고리즘

백준 17822 원판 돌리기

728x90

 

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

 

17822번: 원판 돌리기

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

www.acmicpc.net

삼성 공채에서 나온 시뮬레이션 문제다.

삼성 역테 A+를 목표로 하거나 공채 코테를 목표로 하려면 1시간 안에는 풀어야 한다고 생각한다.

주의 할 점은 시뮬레이션에서 지우거나 없애거나 바꾸거나의 동작을 할 경우 항상 예외를 생각해야한다.

이 문제의 경우 3가지 정도 까다로운 점이 있다.

 

1. 회전시키기

회전시키려는 배열의 크기가 작다면 임시 배열을 만들어서 회전시키는 걸 추천한다. 실수할 확률이 정말 많이 줄어든다.

 

2. 평균 구하기

이 문제에서는 평균을 구해야한다. 하지만 count = 0 일 경우 평균을 구할때 divide by zero exception(RTE)이 발생할 것이다. 그러므로 count =0 인 경우를 생각해야 한다. 

또 이 문제의 경우, 평균을 생각할때 소수부분까지 구해야한다. double 간의 비교는 매우 복잡하기 때문에(특히 == 의 경우) 나눠서 평균을 구하기보다는 * count 한 값을 비교해줘서 double 간의 비교를 Integer 간의 비교로 바꾼다.

 

3. 마지막으로 숫자을 지울때 어느시점에 지울지 분명히 생각해야한다. 지우는 연산은 배열을 파싱하는 도중에 하면 예외사항이 생길수 있다. 지워야할 위치를 배열로 저장한 다음 파싱이 모두 끝난 후에 지우자.

 

 

import java.util.*;
import java.io.*;

public class Main {
	static class MyScanner {
		BufferedReader bf;
		StringTokenizer st;

		MyScanner() {
			bf = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(bf.readLine());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}
	}

	static void printMap(int map[][], int N, int M) {
		for (int i = 1; i <= N; i++) {
			for (int j = 0; j < M; j++) {
				System.out.print(map[i][j] + " ");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyScanner sc = new MyScanner();

		int N = sc.nextInt();
		int M = sc.nextInt();
		int T = sc.nextInt();

		int map[][] = new int[N + 2][M];

		for (int i = 1; i <= N; i++) {
			for (int j = 0; j < M; j++) {
				map[i][j] = sc.nextInt();
			}
		}

		for (int i = 0; i < T; i++) {
			int x = sc.nextInt();
			int d = sc.nextInt();
			int k = sc.nextInt();

			for (int j = x; j <= N; j += x) { // x의 배수 회전
				if (d == 0) { // 시계 방향 회전
					k %= M;
					int tempa[] = new int[M];
					for (int ii = 0; ii < M; ii++) {
						tempa[ii] = map[j][ii];
					}
					for (int ii = 0; ii < M; ii++) {
						map[j][(ii + k) % M] = tempa[ii];
					}

				} else { // 반시계방향 회전
					k %= M;

					int tempa[] = new int[M];
					for (int ii = 0; ii < M; ii++) {
						tempa[ii] = map[j][ii];
					}
					int temp = map[j][0 + k];
					for (int ii = 0; ii < M; ii++) {
						map[j][ii] = tempa[(ii + k) % M];
					}
					map[j][0] = temp;
				}
			}

			boolean avg = false;
			boolean flag[][] = new boolean[N + 1][M];
			for (int ii = 1; ii <= N; ii++) { //지워야 할 위치 저장
				for (int jj = 0; jj < M; jj++) {

					if (map[ii][jj] != 0 && map[ii + 1][jj] == map[ii][jj]) {
						flag[ii][jj] = true;
						avg = true;
					}
					if (map[ii][jj] != 0 && map[ii - 1][jj] == map[ii][jj]) {
						flag[ii][jj] = true;
						avg = true;
					}
					if (map[ii][jj] != 0 && map[ii][(jj + 1) % M] == map[ii][jj]) {
						flag[ii][jj] = true;
						avg = true;
					}
					if (map[ii][jj] != 0 && map[ii][(jj - 1 + M) % M] == map[ii][jj]) {
						flag[ii][jj] = true;
						avg = true;
					}

				}
			}

			if (!avg) { // 지워야할 수가 없는 경우
				int count = 0;
				int sum = 0;
				for (int iii = 1; iii <= N; iii++) {
					for (int jjj = 0; jjj < M; jjj++) {
						if (map[iii][jjj] > 0) {
							count++;
							sum += map[iii][jjj];
						}
					}
				}
				if (count == 0)
					continue;

				for (int iii = 1; iii <= N; iii++) {
					for (int jjj = 0; jjj < M; jjj++) {
						if (map[iii][jjj] > 0) {
							if (sum == map[iii][jjj] * count) { //평균이 아닌 Integer 간 의 비교로 치환
								continue;
							} else if (sum > map[iii][jjj] * count) {
								map[iii][jjj]++;
							} else if (sum < map[iii][jjj] * count) {
								map[iii][jjj]--;
							}
						}
					}
				}
			} 
			else { //지울 수가 있는 경우 위치 배열을 이용하여 지우자
				for (int ii = 1; ii <= N; ii++) {
					for (int jj = 0; jj < M; jj++) {
						if (flag[ii][jj])
							map[ii][jj] = 0;
					}
				}
			}

		}

		int answer = 0;
		for (int i = 1; i <= N; i++) {
			for (int j = 0; j < M; j++) {
				answer += map[i][j];
			}
		}
		System.out.println(answer);

	}

}

'알고리즘' 카테고리의 다른 글

창발성  (0) 2021.07.03
백준 7571 점모으기  (0) 2020.05.11
백준 2610 회의준비  (0) 2020.04.18