알고리즘

백준 17822번 원판 돌리기 (JAVA)

박카스마시며코딩 2022. 8. 8. 13:39

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

 

17822번: 원판 돌리기

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

www.acmicpc.net

 

저는 구현을 통해 문제를 해결하였습니다.

저는 2차원 배열을 통해 원판을 표현하여 인접한 것을 체크하기 용이하게 코드를 작성하였습니다.

 

package BOJ.simulation;

import java.awt.print.Pageable;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.function.Function;

public class BOJ_17822 {
    private static final int EMPTY = 0;
    private static final int CLOCKWISE = 0;
    private static final int COUNTERCLOCKWISE = 1;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        Function<String,Integer> stoi = Integer::parseInt;
        int n = stoi.apply(st.nextToken());
        int m = stoi.apply(st.nextToken());
        int t = stoi.apply(st.nextToken());
        int[][] input = new int[n+1][m];

        for(int i = 1 ; i <= n ; i++){
            st = new StringTokenizer(br.readLine());
            for(int j = 0 ; j < m ; j++){
                input[i][j] = stoi.apply(st.nextToken());
            }
        }
        for(int i = 0 ; i < t; i++){
            st = new StringTokenizer(br.readLine());
            int x = stoi.apply(st.nextToken());
            int d = stoi.apply(st.nextToken());
            int k = stoi.apply(st.nextToken());
            rotate(input,x,d,k,n,m);
            checkNear(input,n,m);
        }
        System.out.println(calScore(input,n,m));
    }
    private static void print(int[][]input,int n,int m){
        for(int i = 1 ; i <= n ; i++){
            System.out.println(Arrays.toString(input[i]));
        }
        System.out.println();
    }
    private static int calScore(int[][] input, int n, int m) {
        int sum = 0;
        for(int i = 1 ; i <= n ; i++){
            for(int j = 0 ; j < m ; j++){
                sum += input[i][j];
            }
        }
        return sum;
    }

    private static final int[] DY = {-1,0,1,0};
    private static final int[] DX = {0,1,0,-1};

    private static void checkNear(int[][] input, int n, int m) {
        boolean[][] near = new boolean[n+1][m];
        boolean findNear = false;
        for(int i = 1 ; i <= n ; i++){
            for(int j = 0 ; j < m ; j++){
                for(int dir = 0 ; dir < 4; dir++){
                    int ny = i + DY[dir];
                    if(ny < 1 || ny > n) {
                        continue;
                    }
                    int nx = j + DX[dir];
                    if(nx < 0){
                        nx = m-1;
                    }
                    if(nx >= m){
                        nx = 0;
                    }
                    if(input[i][j] == input[ny][nx] && input[i][j] != EMPTY){
                        findNear = true;
                        near[i][j] = true;
                        near[ny][nx] = true;
                    }
                }
            }
        }
        if(!findNear){
            int sum = 0;
            int cnt = 0;
            for(int i = 1 ; i <= n ; i++){
                for(int j = 0 ; j < m ; j++){
                    if(input[i][j] != EMPTY){
                        cnt++;
                        sum += input[i][j];
                    }
                }
            }
            double avg = (double)sum/cnt;
            for(int i = 1 ; i <= n ; i++){
                for(int j = 0 ; j < m ; j++){
                    if(input[i][j] == EMPTY){
                        continue;
                    }
                    if(input[i][j] > avg ){
                        input[i][j]--;
                        continue;
                    }
                    if(input[i][j] < avg){
                        input[i][j]++;
                        continue;
                    }
                }
            }
            return;
        }
        for(int i = 1 ; i <= n ; i++){
            for(int j = 0 ; j < m ; j++){
                if(near[i][j]){
                    input[i][j] = EMPTY;
                }
            }
        }
    }

    private static void rotate(int[][] input, int x, int d, int k, int n, int m) {
        for(int i = 1 ; i <= n ; i++){
            if(i % x == 0){
                for(int a = 0 ; a < k ; a++){

                    if(d == CLOCKWISE){

                        int prev = input[i][m-1];
                        for(int j = 0 ; j < m ; j++){
                            int temp = input[i][j];
                            input[i][j] = prev;
                            prev = temp;
                        }
                    }else{
                        int prev = input[i][0];
                        for(int j = m-1 ; j >= 0 ; j--){
                            int temp = input[i][j];
                            input[i][j] = prev;
                            prev = temp;
                        }
                    }
                }
            }
        }
    }
}