728x90
https://www.acmicpc.net/problem/20058
20058번: 마법사 상어와 파이어스톰
마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다. 오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c
www.acmicpc.net
728x90
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int N;
static int Q;
static int mapSize;
static int[][] map;
static int[] L;
static int[] dx = {-1, 1, 0, 0};
static int[] dy = {0, 0, -1, 1};
static int resultSum;
static int resultCount;
private static void init() throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
Q = Integer.parseInt(st.nextToken());
mapSize = (int)Math.pow(2, N);
map = new int[mapSize][mapSize];
for (int i = 0; i < mapSize; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < mapSize; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
L = new int[Q];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < Q; i++) {
L[i] = Integer.parseInt(st.nextToken());
}
}
private static void play() {
for (int i = 0; i < Q; i++) {
// 맵 부분 격자로 나눈 구역 별로 90도 회전
turn(L[i]);
// 얼음 녹이기
melt();
}
// 답 구하기
getResult();
}
private static void turn(int l) {
int[][] subMap; // 90도 회전한 맵 저장
int subMapSize = (int)Math.pow(2, l);
for (int i = 0; i < mapSize; i += subMapSize) { // 부분 격자로 나눈 구역 별로
for (int j = 0; j < mapSize; j += subMapSize) {
subMap = new int[subMapSize][subMapSize];
for (int k = 0; k < subMapSize ; k++) { // 90도 회전
for (int m = 0; m < subMapSize; m++) {
subMap[k][m] = map[(subMapSize - 1) + i - m][j + k];
}
}
for (int k = 0; k < subMapSize; k++) { // 회전한 정보 맵에 저장
for (int m = 0; m < subMapSize; m++) {
map[i + k][j + m] = subMap[k][m];
}
}
}
}
}
private static void melt() {
int[][] tmpMap = new int[mapSize][mapSize];
int count, nx, ny;
for (int i = 0; i < mapSize; i++) {
for (int j = 0; j < mapSize; j++) {
count = 0; // 인접한 얼음 칸의 개수
for (int k = 0; k < 4; k++) {
nx = i + dx[k];
ny = j + dy[k];
if(nx >= 0 && nx < mapSize && ny >= 0 && ny < mapSize) {
if(map[nx][ny] != 0) count++;
}
}
if(count >= 3) tmpMap[i][j] = map[i][j];
else tmpMap[i][j] = map[i][j] > 0 ? map[i][j] - 1 : 0;
}
}
map = tmpMap;
}
private static void getResult() {
for (int i = 0; i < mapSize; i++) {
for (int j = 0; j < mapSize; j++) {
if(map[i][j] != 0) resultCount = Math.max(resultCount, bfs(i, j));
}
}
}
private static int bfs(int x, int y) {
Queue<int[]> q = new LinkedList<>();
q.add(new int[] {x, y});
resultSum += map[x][y];
map[x][y] = 0;
int ret = 1;
int nx, ny;
while(!q.isEmpty()) {
int[] now = q.poll();
for (int i = 0; i < 4; i++) {
nx = now[0] + dx[i];
ny = now[1] + dy[i];
if(nx >= 0 && nx < mapSize && ny >= 0 && ny < mapSize) {
if(map[nx][ny] != 0) {
resultSum += map[nx][ny];
map[nx][ny] = 0;
ret++;
q.add(new int[] {nx, ny});
}
}
}
}
return ret;
}
public static void main(String[] args) throws Exception{
// 입력
init();
// 시뮬레이션 시작
play();
// 답 출력
System.out.println(resultSum + "\n" + resultCount);
}
}
728x90
'Problem Solving > BOJ' 카테고리의 다른 글
[백준, BOJ 1938] 통나무 옮기기 (java) (0) | 2023.05.14 |
---|---|
[백준, BOJ 9489] 사촌 (java) (0) | 2023.05.14 |
[백준, BOJ 20057] 마법사 상어와 토네이도 (java) (0) | 2023.05.03 |
[백준, BOJ 15657] N과 M (8) (java) (0) | 2023.05.03 |
[백준, BOJ 15652] N과 M (4) (java) (0) | 2023.05.03 |