μ•Œκ³ λ¦¬μ¦˜/λ°±μ€€

[ λ°±μ€€ / BOJ 17822 ] μ›νŒ 돌리기 ( μžλ°” / JAVA )

KIMHYEYUN 2022. 2. 7. 19:57
λ°˜μ‘ν˜•

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

 

17822번: μ›νŒ 돌리기

λ°˜μ§€λ¦„μ΄ 1, 2, ..., N인 μ›νŒμ΄ 크기가 μž‘μ•„μ§€λŠ” 순으둜 λ°”λ‹₯에 λ†“μ—¬μžˆκ³ , μ›νŒμ˜ 쀑심은 λͺ¨λ‘ κ°™λ‹€. μ›νŒμ˜ λ°˜μ§€λ¦„μ΄ i이면, κ·Έ μ›νŒμ„ i번째 μ›νŒμ΄λΌκ³  ν•œλ‹€. 각각의 μ›νŒμ—λŠ” M개의 μ •μˆ˜κ°€ μ ν˜€

www.acmicpc.net

λ¬Έμ œμ„€λͺ…

λ°˜μ§€λ¦„μ΄ 1,2,...,N인 μ›νŒμ΄ 크기가 μž‘μ•„μ§€λŠ” 순이고, 쀑심이 λͺ¨λ‘ κ°™μŒ
λ°˜μ§€λ¦„μ΄ i이면 i번째 μ›νŒ
각각의 μ›νŒμ—λŠ” M개의 μ •μˆ˜κ°€ 쑴재, (i,j) πŸ‘‰ i번째 μ›νŒμ— 적힌 j번째 수의 μœ„μΉ˜

  • (i,1)은 (i,2), (i,M)κ³Ό 인접
  • (i,M)은 (i,1), (i,M-1)κ³Ό 인접
  • (i,j)λŠ” (i,j-1), (i,j+1)κ³Ό 인접 (2<=j<= M-1)
  • (1,j)λŠ” (2,j)와 인접
  • (N,j)λŠ” (N-1,j)와 인접
  • (i,j)λŠ” (i-1,j), (i+1,j)와 인접 (2<=i<=N-1)

각 μ›νŒμ˜ νšŒμ „μ€ λ…λ¦½μ μœΌλ‘œ 진행됨

총 T번 νšŒμ „, i번째 νšŒμ „ν•  λ•Œ μ‚¬μš©λ˜λŠ” λ³€μˆ˜λŠ” $x_i, d_i, k_i$

  1. λ²ˆν˜Έκ°€ $x_i$의 배수인 μ›νŒμ„ $d_i$λ°©ν–₯으둜 $k_i$μΉΈ νšŒμ „
    • $d_i$ == 0 πŸ‘‰ μ‹œκ³„ λ°©ν–₯
    • $d_i$ == 1 πŸ‘‰ λ°˜μ‹œκ³„ λ°©ν–₯
  2. μ›νŒμ— μˆ˜κ°€ λ‚¨μ•„μžˆμœΌλ©΄, μΈμ ‘ν•˜λ©΄μ„œ 같은 수λ₯Ό λͺ¨λ‘ 찾음
    1) μΈμ ‘ν•˜κ³  같은 μˆ˜κ°€ μ—†λ‹€λ©΄
     - μ‘΄μž¬ν•˜λŠ” 수의 평균을 κ΅¬ν•˜κ³ , 평균보닀 큰 수 -= 1, 평균보닀 μž‘μ€ 수 += 1
    2) μžˆλ‹€λ©΄, 찾은 수λ₯Ό λͺ¨λ‘ 지움

T번 νšŒμ „ ν›„, μ›νŒμ— 적힌 수의 합을 좜λ ₯

 

λ¬Έμ œν’€μ΄

disc[N+1][M] : 1번 μ›νŒ ~ N번 μ›νŒμ˜ 각 μˆ«μžλ“€μ΄ μ €μž₯된 λ°°μ—΄

1) νšŒμ „

rotateDisc(x, d, k)
int dir = d == 0 ? 1 : -1;
↑ λ°˜μ‹œκ³„ λ°©ν–₯이라면 μ•žμœΌλ‘œ 이동, μ‹œκ³„λ°©ν–₯이라면 λ’€λ‘œ μ΄λ™μ΄κΈ°λ•Œλ¬Έμ—

μž„μ˜μ˜ λ°°μ—΄ tmp에 이동결과 μ €μž₯
tmp[j + (dir * (k % M)) + M) % M] = disc[i][j];

κ·Έ ν›„, μ›λž˜ λ°°μ—΄ disc에 μ €μž₯

2) μΈμ ‘ν•œ 같은 숫자 쑴재 확인

discλ‚΄μ˜ 0이 μ•„λ‹Œ λͺ¨λ“  μˆ˜μ— λŒ€ν•΄
BFS μ΄μš©ν•΄μ„œ 같은 κ°’ μ°ΎκΈ°

ν–‰ μΈλ±μŠ€μ— λŒ€ν•΄μ„œλŠ” 0 < nx <= N인 λΆ€λΆ„λ§Œ μ§„ν–‰,
μ—΄ μΈλ±μŠ€μ— λŒ€ν•΄μ„œλŠ”

1) if(ny == M) ny = 0;
2) if(ny == -1) ny = M-1;
둜 λ³€κ²½ν•΄μ€Œ

Boolean isSame πŸ‘‰ κ·Έ 값에 λŒ€ν•΄μ„œ λ³€κ²½ν•˜κΈ° μœ„ν•œ λ³€μˆ˜
Boolean isChange πŸ‘‰ 전체 확인 ν›„, μΈμ ‘ν•œ 같은 κ°’ μ‚­μ œ 확인 μœ„ν•œ λ³€μˆ˜

3) 평균 κ΅¬ν•˜κ³  숫자 λ³€κ²½

λ§Œμ•½ μœ„μ˜ isChange λ³€μˆ˜κ°€ false라면,
평균을 κ΅¬ν•˜κΈ° πŸ‘‰ calAverage()
κ·Έ ν›„, 평균값에 따라 숫자 λ³€κ²½ πŸ‘‰ changeNum(float sum)

3) λͺ¨λ“  μ›νŒμ˜ 숫자 ν•© 좜λ ₯

 

μ½”λ“œ

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 N, M, T, x, d, k;
    static int[][] disc;
    static boolean[][] isVisited;
    static int[] dx = {-1, 0, 0, 1};
    static int[] dy = {0, -1, 1, 0};
    static boolean isSame, isChange = false;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stringTokenizer = new StringTokenizer(br.readLine());

        N = Integer.parseInt(stringTokenizer.nextToken());
        M = Integer.parseInt(stringTokenizer.nextToken());
        T = Integer.parseInt(stringTokenizer.nextToken());

        disc = new int[N + 1][M];
        for (int i = 1; i < N + 1; i++) {
            stringTokenizer = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                disc[i][j] = Integer.parseInt(stringTokenizer.nextToken());
            }
        }

        while (T-- > 0) {
            stringTokenizer = new StringTokenizer(br.readLine());
            x = Integer.parseInt(stringTokenizer.nextToken());
            d = Integer.parseInt(stringTokenizer.nextToken());
            k = Integer.parseInt(stringTokenizer.nextToken());

            rotateDisc(x, d, k);
//            System.out.println("x : " +x +" d: " + d +" k: " +k );
//            tostring();
            isChange = false;
            for (int i = 1; i <= N; i++) {
                for (int j = 0; j < M; j++) {
                    isSame = false;
                    if(disc[i][j] != 0) {
                        checkAdjNum(i, j, disc[i][j]);
                        if(isSame) {
                            disc[i][j] = 0;
/*                            System.out.println("i : "+i+" j : "+j );
                            tostring();*/
                        }
                    }
                }
            }

            if (!isChange) {
                calAverage();
            }
        }

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

    private static void tostring() {
        for (int[] di : disc) {
            for (int d : di) {
                System.out.print(d + " ");
            }
            System.out.println();
        }
        System.out.println();
    }

    private static void calAverage() {
//        System.out.println("calAverage()");
        float sum = 0;
        float cnt = 0;
        for (int i = 1; i <= N; i++) {
            for (int j = 0; j < M; j++) {
                sum += disc[i][j];
                if(disc[i][j] != 0) cnt += 1;
            }
        }

        sum /= cnt;
        changeNum(sum);
    }

    private static void changeNum(float sum) {
//        System.out.println("sum: " + sum);
        for (int i = 1; i <= N; i++) {
            for (int j = 0; j < M; j++) {
                if(disc[i][j] != 0){
                    if(disc[i][j] < sum) disc[i][j] += 1;
                    else if(disc[i][j] > sum) disc[i][j] -= 1;
                }
            }
        }
//        tostring();
    }

    private static void checkAdjNum(int x, int y, int value) {
        isVisited = new boolean[N + 1][M];
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[]{x, y});
        isVisited[x][y] = true;

        while (!q.isEmpty()) {
            int[] now = q.poll();

            for (int i = 0; i < 4; i++) {
                int nx = now[0] + dx[i];
                int ny = now[1] + dy[i];
                if(ny == M) ny = 0;
                if(ny == -1) ny = M - 1;

                if(nx <= 0 || N < nx || isVisited[nx][ny] || disc[nx][ny] != value) continue;

                q.add(new int[]{nx, ny});
                isVisited[nx][ny] = true;
                disc[nx][ny] = 0;
                isSame = true;
                isChange = true;
            }
        }

    }

    private static void rotateDisc(int x, int d, int k) {
        // νšŒμ „
        int dir = d == 0 ? 1 : -1;
        for (int i = x; i < N + 1; i += x) {
            int[] tmp = new int[M];
            for (int j = 0; j < M; j++) {
                tmp[(j + (dir * (k % M)) + M) % M] = disc[i][j];

            }
            disc[i] = Arrays.copyOf(tmp, M);
        }
    }
}
728x90
λ°˜μ‘ν˜•