본문 바로가기

알고리즘/SW 역량 테스트

[백준] 21610. 마법사 상어와 비바라기

반응형

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

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net


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

public class Main {
	
	public static class Pair {
		int x;
		int y;
		
		Pair(int x, int y){
			this.x=x;
			this.y=y;
		}
	}

	static int N, M, d, s;
	static int[][] map;
	static int[][] dir = { { 0, 0 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 } };
	static boolean[][] check;
//	static int[][] change_dir = {{0,0}, {0, N}, {N, N}, {N, 0}, {N, 1}, {}};
	static ArrayList<Pair> clouds = new ArrayList();

	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());
		M = Integer.parseInt(st.nextToken());

		map = new int[N + 1][N + 1];
		check = new boolean[N + 1][N + 1];
		clouds.add(new Pair(N, 1));
		clouds.add(new Pair(N, 2));
		clouds.add(new Pair(N-1, 1));
		clouds.add(new Pair(N-1, 2));
		
		for (int i = 1; i <= N; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			for (int j = 1; j <= N; j++) {
				map[i][j] = Integer.parseInt(st.nextToken());
			}
		}
		
		for(int i=0; i<M; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			d = Integer.parseInt(st.nextToken());
			s = Integer.parseInt(st.nextToken());
			
			// d 방향으로 s만큼 구름 이동
			for(int j=0; j<s; j++) {
				for(int k=0; k<clouds.size(); k++) {
					Pair p = clouds.get(k);
					int nx = p.x + dir[d][0];
					int ny = p.y + dir[d][1];
					
					if(!isInside(nx, ny)) {
						if(nx == 0) nx = N;
						else if(nx == N+1) nx = 1;
							
						if(ny == 0) ny = N;
						else if(ny == N+1) ny = 1;
					}
					clouds.set(k, new Pair(nx, ny));
					
//					System.out.println("이동한 구름 좌표 : " + nx + " " + ny);
				}
			}
			
			// 구름이 있는 칸에 비가 1씩 내리고, 구름은 사라진다.
			for(int j=0; j<clouds.size(); j++) {
				Pair p = clouds.get(j);
				map[p.x][p.y] += 1;
				
				// 구름 표시
				check[p.x][p.y] = true;
			}
			
			for(int j=0; j<clouds.size(); j++) {
				Pair p = clouds.get(j);
				
				int cnt = 0;
			
				// 대각선 방향 물 확인
				for(int k=2; k<=8; k+=2) {
					int nx = p.x+dir[k][0];
					int ny = p.y+dir[k][1];
					
					if(isInside(nx, ny) && map[nx][ny] != 0) cnt++; 
				}
				// 대각선 방향 물의 갯수만큼 양 증가.
				map[p.x][p.y] += cnt;
			}
			
			// 구름이 사라진다.
			clouds.clear();
			
			// 구름이 있었던 칸을 제외한 나머지 칸 중에 물의 양이 2 이상인 칸에 구름이 생긴다.
			// 구름이 생기면 물의 양이 2만큼 줄어든다.
			for(int j=1; j<=N; j++) {
				for(int k=1; k<=N; k++) {
					// 구름이 있었던 칸 제외
					if(check[j][k]) continue;
					
					// 2 이상인 칸에 구름이 생기고 물의양 2줄어듬
					if(map[j][k] >= 2) {
						map[j][k] -= 2;
						clouds.add(new Pair(j, k));
//						System.out.println("구름 좌표 : " + j + ", " + k);
					}
				}
			}
			
			check = new boolean[N+1][N+1];
			
			// print();
		}
		
		int answer = 0;
		
		// 물의 양의 합
		for(int i=1; i<=N; i++) {
			for(int j=1; j<=N; j++) {
				answer += map[i][j];
			}
		}
		
		System.out.println(answer);

	}
	
	public static boolean isInside(int x, int y) {
		return x>=1 && y>=1 && x<=N && y<=N;
	}
	
	public static void print_clouds() {
		for(int i=1; i<=N; i++) {
			for(int j=1; j<=N; j++) {
				if(check[i][j]) System.out.print("1 ");
				else System.out.print("0 ");
			}
			System.out.println();
		}
		System.out.println();
	}
	
	public static void print() {
		for(int i=1; i<=N; i++) {
			for(int j=1; j<=N; j++) {
				System.out.print(map[i][j] + " ");
			}
			System.out.println();
		}
		System.out.println();
	}
}
반응형