본문 바로가기

ProgramSoliving

백준 : 17822 JAVA

반응형

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

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀있고, i번째 원판에 적힌 j번째 수의 위치는 (i, j)로 표현한다. 수의 위치는 다음을 만족한다. (i, 1)은 (i, 2), (i, M)과 인접하다. (i, M)은 (i, M-1), (i, 1)과 인접하다. (i, j)는 (i, j-1), (i, j

www.acmicpc.net

글에 대한 설명이 턱없이 부족하다. 문제를 풀면서 테스트 케이스를 돌려보면서 확인해야한다.

 

1. 원판은 시작할때는 인접한 것을 check하지 않는다. 시작하자마자 인접하는 것을 지우고 돌리면 예제 case가 나오지 않는다.

 

2. 돌리고 나서 인접한 case가 없다면 아무것도 지우지 않게되는데 이때 합을구하고 평균을 내는데 평균은

전체 원판의 수가아닌 활성화된 원판의 수를 의미한다.

 

3. 평균에서 같은 값은 아무 처리하지 않는다.

 

4. 시간을 올리게 하기 위해선 돌아간 원판의 위치에서 같은 인자값을 해줘도된다 (소스에서는 처리하지않음)

 

 

문제를 풀때는 2차원 배열로 원판을 구현하고 배열 좌우는 연결되있다고 가정한다. LinkedList보단 배열의 인자값을 M일때 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
 
public class B17822 {
    static int N, M, T;
    static int[][] One;
    static int[][] Seq;
    static int[] dy = { 001-1 };
    static int[] dx = { 1-100 };
    static boolean check;
    static boolean[][] checkMap;
 
    public static void main(String[] args) throws IOException {
        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());
        T = Integer.parseInt(st.nextToken());
 
        One = new int[N][M];
        Seq = new int[T][3];
 
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < M; j++) {
                One[i][j] = Integer.parseInt(st.nextToken());
            }
        }
 
        for (int i = 0; i < T; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < 3; j++) {
                Seq[i][j] = Integer.parseInt(st.nextToken());
            }
        }
 
        // RotateGo
        for (int t = 0; t < T; t++) {
            int x = Seq[t][0];
            int d = Seq[t][1];
            int k = Seq[t][2];
            // 배수들은 다회전 시키기 0 :시계 1:반시계
 
            for (int i = x - 1; i < N; i += x) {
                Rotate(i, d, k);
 
            }
 
            // 인접한게 있나? 있으면 지우기
            check = false;
            checkMap = new boolean[N][M];
            for (int i = 0; i < N; i++) {
                OneCheck(i);
            }
            if (!check) {
                // 평균을 구하고
                // 인접한게 하나도 없으면 sum -1 sum+1
                isNot();
            }
        }
 
 
        // 모든 원판의 합
        System.out.println(Answer());
    }
 
    public static void Rotate(int x, int d, int k) {
        k %= M;
        if (k == 0)
            return;
 
        // 반시계방향 k번 회전은
        // 시계방향 M-k 번 회전과 같다
        if (d == 0) {
            // 시계 방향
            for (int kk = 0; kk < k; kk++) {
 
                int tmp = One[x][M - 1];
                for (int i = M - 1; i >= 1; i--) {
                    One[x][i] = One[x][i - 1];
                }
                One[x][0= tmp;
            }
 
        } else {
            for (int kk = 0; kk < M - k; kk++) {
 
                int tmp = One[x][M - 1];
                for (int i = M - 1; i >= 1; i--) {
                    One[x][i] = One[x][i - 1];
                }
                One[x][0= tmp;
            }
 
        }
    }
 
    // 원판 check
    public static void OneCheck(int x) {
        for (int j = 0; j < M; j++) {
            if (One[x][j] == 0 || checkMap[x][j])
                continue;
            // 좌우밑왼 check
            int ny, nx;
            for (int d = 0; d < 4; d++) {
                ny = x + dy[d];
                nx = j + dx[d];
 
                if (ny < 0 || ny >= N)
                    continue;
 
                if (nx == -1)
                    nx = M - 1;
                else if (nx == M)
                    nx = 0;
 
                if (One[x][j] == One[ny][nx]) {
                    DFS(x, j, One[x][j]);
                    check = true;
                }
            }
 
        }
    }
 
    // 원판 돌면서 같은값 0으로 초기화 하기
    public static void DFS(int y, int x, int eraser) {
        int ny;
        int nx;
 
        if (checkMap[y][x])
            return;
        if (One[y][x] == 0)
            return;
 
        if (One[y][x] == eraser) {
            One[y][x] = 0;
            checkMap[y][x] = true;
        }
 
        for (int d = 0; d < 4; d++) {
            ny = y + dy[d];
            nx = x + dx[d];
 
            if (ny < 0 || ny >= N)
                continue;
 
            if (nx == -1)
                nx = M - 1;
            else if (nx == M)
                nx = 0;
 
            if (One[ny][nx] == 0)
                continue;
 
            if (One[ny][nx] == eraser) {
                if (!checkMap[ny][nx]) {
                    DFS(ny, nx, eraser);
                }
            }
        }
    }
 
    public static void isNot() {
        int sum = 0;
        int cnt = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (One[i][j] == 0)
                    continue;
                cnt++;
                sum += One[i][j];
            }
        }
 
        double avg = (double) sum / (cnt);
 
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (One[i][j] == 0)
                    continue;
 
                if (One[i][j] > avg) {
                    One[i][j] += -1;
                } else if(One[i][j] < avg){
                    One[i][j] += 1;
                }
            }
        }
 
    }
 
    public static int Answer() {
        int sum = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                sum += One[i][j];
            }
        }
 
        return sum;
    }
 
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
반응형

'ProgramSoliving' 카테고리의 다른 글

백준 : 17142  (0) 2020.02.03
백준 : 17143  (0) 2020.02.03
백준 : 16236 JAVA  (0) 2020.02.02
백준 : 5373*  (0) 2020.02.01
백준 : 13548  (0) 2020.01.30