알고리즘 문제 풀이/BOJ

[backjoon]17822 원판 돌리기 java

v 2022. 4. 25. 21:00

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

 

17822번: 원판 돌리기

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

www.acmicpc.net

원형이라고 해서 겁먹었는데 2차원 배열과 모듈러 연산을 이용해서 풀이하면 쉽게 풀 수 있다.

문제를 살펴보면 구현해야할 것은

1. 원판 이동

-  Queue를 이용해서 이동 하는 칸 수 만큼 모듈러 연산을 이용하여 저장 후 이동시켜주었다. move()

2. 인접한 값들의 확인.

- 원판 이동 후 인접한 값들에 대해 확인하는 것은 일일이 다 비교를 해주었다. 값이 크지 않기 때문에 가능했고, 속도도 그렇게 느리지 않았다. 인접한 값들은 boolean type의 이차원 배열을 이용해서 표시했다.

- 인접한 값들 중에 동일한 값이 없으면 평균을 기준으로 큰 값은 하나 빼고 작은 값은 하나 더하기. 절대절대 비교할 때 소수값을 비교해줘야한다!!!

- 인접한 값들 중에 동일한 값이 있으면 표시한 값들을 확인해가며 제거해준다. 원판위의 값들이 1보다 크다는 것을 이용해서 제거를 0으로 처리하였다.

이렇게 네 가지 정도가 구현 요소라고 생각된다.

 

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import java.io.*;
import java.util.*;
 
public class Main {
    static int[][] map;
    static int N, M;
 
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        int T = Integer.parseInt(st.nextToken());
        map = new int[N][M];
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        int answer = 0;
        while (T-- > 0) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken());
            int d = Integer.parseInt(st.nextToken());
            int k = Integer.parseInt(st.nextToken());
            for (int i = x - 1; i < N; i += x) {
                move(i, d, k);
            }
            // 검증하기
            verify();
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                answer += map[i][j];
            }
        }
        System.out.println(answer);
    }
 
    private static void verify() {
        boolean[][] marked = new boolean[N][M];
        boolean flag = false;
        // 위부터 확인.
        for (int i = 0; i < N - 1; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] == 0)
                    continue;
                if (map[i][j] == map[i + 1][j]) {
                    flag = true;
                    marked[i][j] = true;
                    marked[i + 1][j] = true;
                }
            }
        }
        // 아래부터 확인
        for (int i = 1; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] == 0)
                    continue;
                if (map[i][j] == map[i - 1][j]) {
                    flag = true;
                    marked[i][j] = true;
                    marked[i - 1][j] = true;
                }
            }
        }
        // 양 옆 확인
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                int col = (j + 1) % M;
                if (map[i][j] == 0)
                    continue;
                if (map[i][j] == map[i][col]) {
                    flag = true;
                    marked[i][j] = true;
                    marked[i][col] = true;
                }
            }
        }
        
        // 반영하기.
        if (!flag) {
            zero();
        } else {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    if (marked[i][j])
                        map[i][j] = 0;
                }
            }
        }
    }
 
    private static void zero() {
        int cnt = 0;
        int sum = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] == 0)
                    continue;
                sum += map[i][j];
                cnt++;
            }
        }
        double avg = (double) sum / cnt;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] == 0)
                    continue;
                if (map[i][j] > avg) {
                    map[i][j]--;
                } else if (map[i][j] < avg) {
                    map[i][j]++;
                }
            }
        }
 
    }
 
    private static void move(int i, int d, int k) {
        if (d == 0)
            k *= -1;
        Queue<Integer> queue = new LinkedList<>();
        for (int j = 0; j < M; j++) {
            int col = k + j + M;
            col %= M;
            int cur = map[i][col];
            queue.add(cur);
        }
        for (int j = 0; j < M; j++) {
            map[i][j] = queue.poll();
        }
    }
}
cs

 

 

 

반응형