Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 23e49e9

Browse files
committed
고다혜: [CT] 회전하는 빙하_241111
1 parent dd15be9 commit 23e49e9

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import java.io.*;
2+
import java.util.*;
3+
4+
public class DH_회전하는_빙하 {
5+
static class Point {
6+
int r, c;
7+
public Point(int r, int c) {
8+
this.r = r;
9+
this.c = c;
10+
}
11+
}
12+
static int N, Q, totalIceCnt, iceSize;
13+
static int[][] map;
14+
static BufferedReader br;
15+
static StringTokenizer st;
16+
static int[] dr = {1, 0, -1, 0}, dc = {0, 1, 0, -1}; // 하, 우, 상, 좌
17+
static boolean[][] v;
18+
static Deque<Point> q;
19+
20+
public static void main(String[] args) throws Exception {
21+
System.setIn(new FileInputStream("./input/회전하는빙하.txt"));
22+
initInput();
23+
solution();
24+
}
25+
26+
static void solution() throws Exception {
27+
st = new StringTokenizer(br.readLine());
28+
29+
while(Q-- > 0) {
30+
int level = Integer.parseInt(st.nextToken());
31+
rotate(level);
32+
melt();
33+
}
34+
35+
// map을 확인하며 영역의 최대 크기와 남아있는 얼음의 양 구하기
36+
checkMapStatus();
37+
38+
StringBuilder sb = new StringBuilder();
39+
sb.append(totalIceCnt).append("\n").append(iceSize);
40+
System.out.println(sb);
41+
}
42+
43+
static void checkMapStatus() {
44+
v = new boolean[map.length][map[0].length];
45+
q = new ArrayDeque<>();
46+
47+
// bfs를 통해 얼음이 있는 영역의 최대 크기와 남아있는 얼음의 양 구하기
48+
for(int r = 0; r < map.length; r++) {
49+
for(int c = 0; c < map[0].length; c++) {
50+
if(v[r][c] || map[r][c] == 0) continue;
51+
bfs(r, c);
52+
}
53+
}
54+
}
55+
56+
static void bfs(int r, int c) {
57+
q.add(new Point(r, c));
58+
v[r][c] = true;
59+
totalIceCnt += map[r][c];
60+
int size = 1;
61+
62+
while(!q.isEmpty()) {
63+
Point current = q.poll();
64+
65+
for(int d = 0; d < 4; d++) {
66+
int nr = current.r + dr[d];
67+
int nc = current.c + dc[d];
68+
69+
if(!check(nr, nc) || v[nr][nc] || map[nr][nc] == 0) continue;
70+
q.add(new Point(nr, nc));
71+
v[nr][nc] = true;
72+
totalIceCnt += map[nr][nc];
73+
size++;
74+
}
75+
}
76+
77+
iceSize = Math.max(iceSize, size);
78+
}
79+
80+
// meltFlag[r][c] == true인 지점 녹이기
81+
static void melt() {
82+
boolean[][] meltFlag = makeMeltFlagMap();
83+
for(int r = 0; r < meltFlag.length; r++) {
84+
for(int c = 0; c < meltFlag[0].length; c++) {
85+
if(!meltFlag[r][c] || map[r][c] == 0) continue;
86+
map[r][c]--;
87+
}
88+
}
89+
}
90+
91+
// 해당 부분이 녹는지 안녹는지 확인하는 meltFlag 변수를 초기화하는 함수
92+
static boolean[][] makeMeltFlagMap() {
93+
boolean[][] meltFlag = new boolean[map.length][map[0].length];
94+
95+
for(int r = 0; r < map.length; r++) {
96+
for(int c = 0; c < map[0].length; c++) {
97+
int iceCnt = 0;
98+
for(int d = 0; d < 4; d++) {
99+
int nr = r + dr[d];
100+
int nc = c + dc[d];
101+
102+
if(!check(nr, nc) || map[nr][nc] == 0) continue;
103+
iceCnt++;
104+
}
105+
106+
if(iceCnt < 3) meltFlag[r][c] = true;
107+
}
108+
}
109+
return meltFlag;
110+
}
111+
static boolean check(int r, int c) {
112+
return r >= 0 && r < map.length && c >= 0 && c < map[0].length;
113+
}
114+
static void rotate(int level) {
115+
int size = (int) Math.pow(2, level);
116+
// r, c: 하늘색 사각형 배열이 시작하는 부분
117+
for(int r = 0; r < map.length; r += size) {
118+
for(int c = 0; c < map[0].length; c += size) {
119+
120+
// map에서 1사분면만 해당되는 부분을 저장
121+
int[][] tmp = copyPart1(r, c, size / 2);
122+
rotate(r, c, level, tmp);
123+
}
124+
}
125+
}
126+
127+
static int[][] copyPart1(int r, int c, int level) {
128+
int[][] tmp = new int[level][level];
129+
for(int sr = r; sr < r + level; sr++) {
130+
for(int sc = c; sc < c + level; sc++) {
131+
tmp[sr - r][sc - c] = map[sr][sc];
132+
}
133+
}
134+
135+
return tmp;
136+
}
137+
138+
static void rotate(int r, int c, int level, int[][] tmp) {
139+
140+
int size = (int) Math.pow(2, level) / 2;
141+
142+
// 반시계 방향으로 돌면서 바꿀 값을 가지고 옴
143+
for(int i = 0; i < 3; i++) {
144+
145+
int nr = r + dr[i] * size;
146+
int nc = c + dc[i] * size;
147+
148+
// rr, cc: 첨부한 사진 level2에서 민트색(?) 부분 배열
149+
// level1에서는 크기가 1 * 1이기 때문에 사진에 표시 안함
150+
for(int rr = 0; rr < size; rr++) {
151+
for(int cc = 0; cc < size; cc++) {
152+
map[r + rr][c + cc] = map[nr + rr][nc + cc];
153+
}
154+
}
155+
156+
r = nr; c = nc;
157+
}
158+
159+
// 처음 부분은 이미 값이 바뀐 상태이기 때문에
160+
// 미리 tmp 값에 저장한 값으로 가져옴
161+
for(int rr = 0; rr < size; rr++) {
162+
for(int cc = 0; cc < size; cc++) {
163+
map[r + rr][c + cc] = tmp[rr][cc];
164+
}
165+
}
166+
}
167+
168+
static void printMap() {
169+
for(int r = 0; r < map.length; r++) {
170+
System.out.println(Arrays.toString(map[r]));
171+
}
172+
}
173+
174+
static void initInput() throws Exception {
175+
br = new BufferedReader(new InputStreamReader(System.in));
176+
st = new StringTokenizer(br.readLine());
177+
178+
N = Integer.parseInt(st.nextToken());
179+
Q = Integer.parseInt(st.nextToken());
180+
181+
int length = (int) Math.pow(2, N);
182+
map = new int[length][length];
183+
184+
for(int r = 0; r < map.length; r++) {
185+
st = new StringTokenizer(br.readLine());
186+
187+
for(int c = 0; c < map[0].length; c++) {
188+
map[r][c] = Integer.parseInt(st.nextToken());
189+
}
190+
}
191+
192+
193+
}
194+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /