Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

Life Engineering

[BOJ 21610] 마법사 상어와 비바라기 (Java) 본문

Problem Solving

[BOJ 21610] 마법사 상어와 비바라기 (Java)

흑개 2022. 4. 19. 22:12

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.Arrays;
import java.util.StringTokenizer;

public class Main_BOJ_21610 {
	static int N, M;
	static int[][] map;
	static ArrayList<int[]> clouds=new ArrayList<>();
	static boolean[][] visited;
	static int[] dr= {0, -1, -1, -1, 0, 1, 1, 1};
	static int[] dc= {-1, -1, 0, 1, 1, 1, 0, -1};
	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][N];
		visited=new boolean[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());
			}
		}
		int[][] initials= {{N-1,0}, {N-1, 1}, {N-2, 0}, {N-2, 1}};
		for (int i=0; i<4; i++) {
			clouds.add(initials[i]);
		}
		for (int i=0; i<8; i++) {
			if (dr[i]<0) dr[i]=(N-1);
			if (dc[i]<0) dc[i]=(N-1);
		}
		for (int i=0; i<M; i++) {
			st=new StringTokenizer(br.readLine());
			int d=Integer.parseInt(st.nextToken())-1;
			int s=Integer.parseInt(st.nextToken());
			move(d, s);
			increment();
			copy();
			clouds.clear();
			process();		
		}
		int answer=0;
		for (int i=0; i<N; i++) {
			for (int j=0; j<N; j++) {
				answer+=map[i][j];
			}
		}
		System.out.println(answer);
	}

	private static void move(int d, int s) {
		int nr, nc;
		for (int i=0; i<clouds.size(); i++) {
			nr=clouds.get(i)[0];
			nc=clouds.get(i)[1];
			if (d%2==0) s=s%N;
			for (int j=0; j<s; j++) {
				nr=(nr+dr[d])%N;
				nc=(nc+dc[d])%N;
			}
			clouds.set(i, new int[] {nr,nc});
		}
	}
	
	private static void increment() {
		int r, c;
		for (int i=0; i<N; i++) {
			Arrays.fill(visited[i], false);
		}
		for (int i=0; i<clouds.size(); i++) {
			r=clouds.get(i)[0];
			c=clouds.get(i)[1];
			map[r][c]++;
			visited[r][c]=true;
		}
	}
	
	private static void copy() {
		int[] diagonal_r= {-1,-1,1,1};
		int[] diagonal_c= {-1,1,1,-1};
		int r, c, nr, nc;
		for (int i=0; i<clouds.size(); i++) {
			int cnt=0;
			r=clouds.get(i)[0];
			c=clouds.get(i)[1];
			for (int j=0; j<4; j++) {
				nr=r+diagonal_r[j];
				nc=c+diagonal_c[j];
				if (nr<0 || nc<0 || nr>=N || nc>=N || map[nr][nc]==0) continue;
				cnt++;
			}
			map[r][c]+=cnt;
		}
		
	}
	
	private static void process() {
		for (int i=0; i<N; i++) {
			for (int j=0; j<N; j++) {
				if (map[i][j]>=2 && !visited[i][j]) {
					map[i][j]-=2;
					clouds.add(new int[] {i,j});
				}
			}
		}
		
	}

}

시뮬레이션 문제

 

문제의 조건에 맞게 구현해주면 된다.

현재 구름의 위치를 ArrayList에 저장하고, 현재 구름이 위치한 공간을 visited 배열로 표현했다.

 

다만 구름을 움직일 때 주의할 점은 1번째 행, 열이 N번째 행, 열과 서로 이어져 있다는 점이다.

이것을 움직일 때 고려해 주기 위해 현재 위치에서 -1만큼 움직이는 것에 대해, N-1 번을 움직이는 것으로 모두 바꿔주었다. (현재 위치+N-1)%N 해주면 현재 위치보다 -1 만큼 움직이는 거리가 나오기 때문이다. 

 

다른 분들의 코드를 보니 이렇게 복잡하게? 할 필요 없고, (이렇게 바꿔준다면 4번 대각선 체크에서 또 delta 배열을 새로 만들어줘야 한다) 

좌표를 움직여 가면서 만약 좌표가 0 미만이 되면 N-1 로 그 좌표를 바꿔주고

N 이상이 되면 0으로 그 좌표를 바꿔주는 형태로 진행을 했다.