구현 문제입니다.
문제 접근 순서는 다음과 같습니다.
- q만큼 반복한다.
- 범위 회전을 한다.
- 인접한 곳을 확인하여 얼음을 녹인다.
- 남아있는 얼음 정보를 구한다.
첫 번째는 q 만큼 반복하면서 회전할 범위 입력 받아 사용하시면 됩니다.
두 번째는 각 범위의 값을 회전하면 됩니다.
private static void rotateIce(int[][] map, int[][] rotated, int x, int y, int size) {
int ex = x + size;
int ey = y + size;
for(int i=x; i<ex; i++){
int cnt = 0;
for (int j = y; j < ey; j++) {
rotated[i][j] = map[ex-1-cnt][size-(ex-i) + y];
cnt++;
}
}
}
회전할 때, 아래 그림처럼 행이 열로 열이 행으로 바뀝니다. 이를 유의하시면 됩니다.
세 번째는 얼음의 인접(상, 하, 좌, 우)를 확인하여 주변에 얼음이 몇 개나 있는지 확인하면 됩니다.
네 번째는 bfs를 통해 얼음 덩어리의 정보를 구하면 됩니다.
[구현 코드]
import java.io.*;
import java.util.*;
public class Main {
private static final String SEPARATOR = " ";
private static final int[] dx = {-1, 1, 0, 0};
private static final int[] dy = {0, 0, -1, 1};
private static int tn;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer stz = new StringTokenizer(br.readLine(), SEPARATOR);
int n = Integer.parseInt(stz.nextToken());
int q = Integer.parseInt(stz.nextToken());
tn = pow(n);
int[][] map = new int[tn][tn];
for (int i = 0; i < tn; i++) {
stz = new StringTokenizer(br.readLine(), SEPARATOR);
for (int j = 0; j < tn; j++) {
map[i][j] = Integer.parseInt(stz.nextToken());
}
}
// 1. q만큼 반복한다.
stz = new StringTokenizer(br.readLine(), SEPARATOR);
while (q-- > 0) {
int l = Integer.parseInt(stz.nextToken());
int size = pow(l);
// 2. 범위 회전을 한다.
int[][] rotated = new int[tn][tn];
for (int i = 0; i < tn; i += size) {
for (int j = 0; j < tn; j += size) {
rotateIce(map, rotated, i, j, size);
}
}
map = rotated;
// 3. 인접한 곳을 확인하여 얼음을 녹인다.
melt(map);
}
boolean[][] visited = new boolean[tn][tn];
int sum = 0;
int size = 0;
// 4. 남아있는 얼음 정보를 구한다.
for(int i=0; i<tn; i++){
for (int j = 0; j < tn; j++) {
if(map[i][j] > 0 && !visited[i][j]){
int[] search = bfs(map, visited, i, j);
sum += search[0];
size = Math.max(size, search[1]);
}
}
}
bw.write(sum + System.lineSeparator() + size);
bw.flush();
bw.close();
br.close();
}
private static int[] bfs(int[][] map, boolean[][] visited, int i, int j) {
Queue<int[]> qu = new LinkedList<>();
qu.add(new int[]{i ,j});
visited[i][j] = true;
int sum = 0;
int size = 0;
while (!qu.isEmpty()){
int[] cn = qu.poll();
sum += map[cn[0]][cn[1]];
size++;
for(int d=0; d<4; d++){
int nx = cn[0] + dx[d];
int ny = cn[1] + dy[d];
if(!inRange(nx, ny) || map[nx][ny] < 1 || visited[nx][ny]) continue;
visited[nx][ny] = true;
qu.add(new int[]{nx, ny});
}
}
return new int[]{sum, size};
}
private static void melt(int[][] map) {
List<int[]> meltIce = new ArrayList<>();
for(int i=0; i<tn; i++){
for (int j = 0; j < tn; j++) {
int adjustIceCount = 0;
if(map[i][j] < 1) continue;
for(int d = 0; d<4; d++){
int nx = i + dx[d];
int ny = j + dy[d];
if(!inRange(nx, ny)) continue;
if(map[nx][ny] > 0) adjustIceCount++;
}
if(adjustIceCount < 3){
meltIce.add(new int[]{i, j});
}
}
}
for (int[] ice : meltIce) {
map[ice[0]][ice[1]] -= 1;
}
}
private static boolean inRange(int x, int y){
return (x>=0 && y>=0 && x<tn && y<tn);
}
private static void rotateIce(int[][] map, int[][] rotated, int x, int y, int size) {
int ex = x + size;
int ey = y + size;
for(int i=x; i<ex; i++){
int cnt = 0;
for (int j = y; j < ey; j++) {
rotated[i][j] = map[ex-1-cnt][size-(ex-i) + y];
cnt++;
}
}
}
private static int pow(int num) {
return (int) Math.pow(2, num);
}
}
'알고리즘' 카테고리의 다른 글
백준 - 20056 마법사 상어와 파이어볼(Java) (0) | 2023.03.21 |
---|---|
백준 - 14890 경사로(Java) (0) | 2023.03.20 |
백준 - 17472 다리 만들기 2(Java) (0) | 2023.03.15 |
백준 - 21609 상어 중학교(Java) (0) | 2023.03.14 |
백준 - 17281 야구(Java) (0) | 2023.03.14 |