연구실에는 다양한 물건들이 존재하는데 바람의 방향을 위 그림과 같이 바꾼다.
물건이 없다면 바람이 흐르는 방향 그대로 흐를 것이다.
에어컨을 기준으로 상하좌우로 바람이 퍼질텐데, 이 바람이 닫는 영역 개수를 구하는 문제이다.
딱히 문제 자체가 어려운 것은 아니였던 것 같다.
그냥 바람 흐르는 방향을 저장하고, 다음 영역에서 이전에 바람이 흐르는 방향을 파악하여 총 영역 개수를 세기만 하면 되는 문제였다.
문제가 된 부분은 "바람의 방향"이다.
예를 들어 빈 공간에 "왼쪽"에서 온 바람과 "위쪽"에서 온 바람은 다르게 처리해줘야한다.
"왼쪽"에서 온 바람이 있기 때문에 해당 영역을 방문했다고 처리해버리면, 다르게 처리해야하는 "위쪽"에서 오는 바람도 이미 방문한 영역이라는 표시때문에 해당 바람의 영향을 고려하지 못한다는 단점이 생겨났다.
이런 단점을 해결하기 위해 visit, 방문 여부 체크 배열을 3차원으로 만들었다.
그리고 마지막 차원에 "방향"을 저장하여 왼쪽에서 왔다면 [0]부분을, 오른쪽에서 왔다면 [1]부분을 True로 만들어주는 등의 방식을 활용하여 방향까지 고려한 방문 여부 체크를 실시하였다.
import java.io.*;
import java.util.*;
class Point {
int x;
int y;
int direction;
public Point(int x, int y, int direction) {
this.x = x;
this.y = y;
this.direction=direction;
}
}
public class Main {
static StringBuilder sb = new StringBuilder();
static FastReader sc = new FastReader();
static int N, M;
static int[][] arr;
static boolean[][][] visit;
static Queue<Point> starts = new LinkedList<>();
public static void main(String[] args) {
N = sc.nextInt();
M = sc.nextInt();
arr = new int[N][M];
visit = new boolean[N][M][5];
// direction
// 1: 오른쪽에서 왔음
// 2: 왼쪽에서 왔음
// 3: 위쪽에서 왔음
// 4: 아래쪽에서 왔음
// visit[x][y][1] : 오른쪽에서 온 바람이 (x,y)를 지나감
// visit[x][y][2] : 왼쪽에서 온 바람이 (x,y)를 지나감
for(int i =0;i<N;i++) {
for(int j =0;j<M;j++) {
arr[i][j] = sc.nextInt();
if(arr[i][j]==9) {
// 4방향으로 바람이 나아가야하므로 Queue에 추가해준다.
starts.add(new Point(i,j-1, 1));
starts.add(new Point(i,j+1, 2));
starts.add(new Point(i+1,j, 3));
starts.add(new Point(i-1,j, 4));
Arrays.fill(visit[i][j],true);
}
}
}
while(!starts.isEmpty()) {
Point p = starts.poll();
if(p.x <0 || p.y<0 || p.x>=N || p.y>=M) continue;
if(visit[p.x][p.y][p.direction]) continue;
visit[p.x][p.y][p.direction] = true;
if(arr[p.x][p.y]==0) {
// 아무런 물체도 없으므로 원래 방향 그대로 바람이 흐른다.
switch(p.direction) {
case 1:
starts.add(new Point(p.x,p.y-1,1));
break;
case 2:
starts.add(new Point(p.x,p.y+1,2));
break;
case 3:
starts.add(new Point(p.x+1,p.y,3));
break;
case 4:
starts.add(new Point(p.x-1,p.y,4));
break;
}
}
// 아래 else if 문들은 물체가 있는 상황이므로 바람 방향에 따라
// Queue에 물체에 맞는 좌표를 Queue에 넣어주면 된다.
else if(arr[p.x][p.y]==1) {
switch(p.direction) {
case 3:
starts.add(new Point(p.x+1,p.y,3));
break;
case 4:
starts.add(new Point(p.x-1,p.y,4));
break;
}
}
else if(arr[p.x][p.y]==2) {
switch(p.direction) {
case 1:
starts.add(new Point(p.x,p.y-1,1));
break;
case 2:
starts.add(new Point(p.x,p.y+1,2));
break;
}
}
else if(arr[p.x][p.y]==3) {
switch(p.direction) {
case 1:
starts.add(new Point(p.x+1,p.y,3));
break;
case 2:
starts.add(new Point(p.x-1,p.y,4));
break;
case 3:
starts.add(new Point(p.x,p.y-1,1));
break;
case 4:
starts.add(new Point(p.x,p.y+1,2));
break;
}
}
else if(arr[p.x][p.y]==4) {
switch(p.direction) {
case 1:
starts.add(new Point(p.x-1,p.y,4));
break;
case 2:
starts.add(new Point(p.x+1,p.y,3));
break;
case 3:
starts.add(new Point(p.x,p.y+1,2));
break;
case 4:
starts.add(new Point(p.x,p.y-1,1));
break;
}
}
}
int ans = 0;
for(int i =0;i<N;i++) {
for(int j =0;j<M;j++) {
// 어떤 방향에서 왔든 한 번이라도 거쳤으면 바람이 흐르는 영역임
if(visit[i][j][1] || visit[i][j][2]
|| visit[i][j][3] || visit[i][j][4]) ans++;
}
}
System.out.println(ans);
}
static class FastReader // 빠른 입력을 위한 클래스
}