본문 바로가기

알고리즘/SW 역량 테스트

[백준] 20058. 마법사 상어와 파이어스톰

반응형

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

 

20058번: 마법사 상어와 파이어스톰

마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다. 오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c

www.acmicpc.net


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	
	static int N, n, Q, count;
	static int[][] map;
	static int[][] temp_map;
	static int[][] dir = {{0,1}, {0,-1}, {1,0}, {-1,0}};
	static boolean[][] visited;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());
		Q = Integer.parseInt(st.nextToken());
		
		n = (int)Math.pow(2, N);
		
		map = new int[n][n];
		temp_map = new int[n][n];
		
		for(int i=0; i<n; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j=0; j<n; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
	
		st = new StringTokenizer(br.readLine());
		
		for(int i=0; i<Q; i++) {
			int temp = (int)Math.pow(2, Integer.parseInt(st.nextToken()));
			
			// map -> temp_map 복사
			for(int j=0; j<n; j++) {
				for(int k=0; k<n; k++) {
					temp_map[j][k] = map[j][k];
				}
			}
			
			// 왼쪽위 꼭짓점에서 temp 만큼 회전
			for(int j=0; j<n; j+=temp) {
				for(int k=0; k<n; k+=temp) {
					rotate(j, k, temp);
				}
			}
			
			// 얼음이 있는 칸 3개 or 그 이상과 인접해 있지 않은 칸은 얼음의 양이 1 줄어든다.
			down();
		}		
		
		
		int sum = 0;
		
		// 남아있는 얼음의 합
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				sum += map[i][j];
			}
		}
		
		int answer = 0;
		
		visited = new boolean[n][n];
		
		// 가장 큰 덩어리가 차지하는 칸의 개수
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				if(!visited[i][j] && map[i][j] != 0) {
					count = 1;
					getBigIce(i, j);
					answer = Math.max(answer, count);
				}
			}
		}
		
		System.out.println(sum);
		System.out.println(answer);
		
	}
	
	public static void getBigIce(int x, int y) {
		visited[x][y] = true;
		
		for(int i=0; i<4; i++) {
			int nx = x + dir[i][0];
			int ny = y + dir[i][1];
			
			if(isInside(nx, ny) && !visited[nx][ny] && map[nx][ny] != 0) {
				count++;
				getBigIce(nx, ny);
			}
		}
	}
	
	public static void down() {
		visited = new boolean[n][n];
		
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				int cnt = 0;
				
				for(int k=0; k<4; k++) {	
					int nx = i + dir[k][0];
					int ny = j + dir[k][1];
					
					if(isInside(nx, ny) && map[nx][ny] != 0) cnt++;
				}
				
				if(cnt < 3) visited[i][j] = true; 
				
			}
		}
		
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				if(visited[i][j] && map[i][j] > 0) map[i][j]--;
			}
		}
	}
	
	public static boolean isInside(int x, int y) {
		return x>=0 && y>=0 && x<n && y<n;
	}
	
	public static void rotate(int x, int y, int len) {
		
		int temp_y=0;
		for(int i=x; i<x+len; i++) {
			int temp_x = 0;
			for(int j=y; j<y+len; j++) {
				map[x+temp_x][y+len-1-temp_y] = temp_map[i][j];
				temp_x++;
			}
			temp_y++;
		}
		
	}
	
	public static void print() {
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				System.out.print(map[i][j] + " ");
			}
			System.out.println();
		}
		System.out.println();
	}
}
반응형