




생각해야 할 조건이 몇 가지 존재한다.
7명의 학생을 선정 할 때는
if (depth == 3) {
bfs(); //벽이 완성 된 상태의 바이러스 안전지대 확인
return;
}
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (map[i][j] == 0) { //벽을 세울 수 있는 빈 공간 이라면
map[i][j] = 1; //현재 위치에 벽을 세우고
dfs(depth + 1); //depth 1 추가 후 재귀
map[i][j] = 0; //현재 위치를 다시 빈공간으로 복귀
//이어서 반복분
}
}
}
if (pY >= 4) { //임도연 파가 4명 이상이면 return
return;
}
if (num == 7) { //이다솜 파가 4명 이상인 상태
checkLinked(start - 1);
} else {
for (int i = start; i < (SIZE * SIZE); i++) {
visited[i / SIZE][i % SIZE] = true;
getPrincess(num + 1, map[i / SIZE][i % SIZE] == 'Y' ? pY + 1 : pY, i+1);
visited[i / SIZE][i % SIZE] = false;
}
}

2차원 배열을 1차원 배열로 위 그림과 같이 표현 할 수 있고 가로 길이(M)로 나누게 된다면 2차원의 index를 구할 수 있다.
import java.io.*;
import java.util.*;
public class Main {
static final int SIZE = 5;
static char[][] map;
static boolean[][] visited;
static boolean[][] bfsVisited;
static int[] dx = {0, 1, 0, -1}; //동 남 서 북
static int[] dy = {1, 0, -1, 0}; //동 남 서 북
static long result = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
map = new char[SIZE][SIZE];
visited = new boolean[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
String line = br.readLine();
map[i] = line.toCharArray();
}
getPrincess(0, 0,0);
bw.write(result + "\n");
bw.flush();
bw.close();
}
static void getPrincess(int num, int pY, int start) {
if (pY >= 4) { //임도연 파가 4명 이상이면 return
return;
}
if (num == 7) { //이다솜 파가 4명 이상인 상태
checkLinked(start - 1);
} else {
for (int i = start; i < (SIZE * SIZE); i++) {
visited[i / SIZE][i % SIZE] = true;
getPrincess(num + 1, map[i / SIZE][i % SIZE] == 'Y' ? pY + 1 : pY, i+1);
visited[i / SIZE][i % SIZE] = false;
}
}
}
static void checkLinked(int start) {
bfsVisited = new boolean[SIZE][SIZE];
Queue<int[]> q = new LinkedList<>();
q.offer(new int[]{start / SIZE, start % SIZE});
bfsVisited[start / SIZE][start % SIZE] = true;
int cnt = 1;
while (!q.isEmpty()) {
int size = q.size();
for (int s = 0; s < size; s++) {
int[] poll = q.poll();
int x = poll[0];
int y = poll[1];
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (0 <= nx && nx < SIZE && 0 <= ny && ny < SIZE) {
if (visited[nx][ny] == true && bfsVisited[nx][ny] == false){
q.offer(new int[] {nx,ny});
cnt++;
bfsVisited[nx][ny] = true;
}
}
}
}
}
if (cnt == 7){
result++;
}
}
}
7명의 여학생을 배정하고 연속되어 있는지를 확인 할 때는 visited 배열을 사용했는데
해당 배열만으로 진행한다면 큐에 데이터를 넣고 꺼내는 과정에서 탐색했던 부분을 반복할 우려가 있다.
따라서 진행했던 부분을 중복하여 탐색하지 않기 위해서 추가 배열 bfsVisited를 선언해서 진행해 주었다.
연속 여부를 체크하는 BFS 탐색이 끝난다면 cnt를 계산 해주는데 cnt를 연속되어 있는 학생의 숫자이다.
cnt == 7이면 칠공주가 완성된 것이다.
DFS , BFS를 사용해서 탐색하는 코드는 구현하는 것에 나름 익숙해져 있는데 전체 배열에서 무작위로 자리를 배정하는 경우는 익숙하지 않았었다.
과거에 비슷하게 배정하는 문제를 풀었던 기억이 얼핏 들어서 연구소 문제를 복기 했다.
다양한 방법으로 접근을 시도 하면서 두가지 방법(반복문 , 1차원 배열 변환) 모두 동일한 결과를 반환 한다는 것을 알아냈고 좀 더 직관적이라고 생각한 1차원 배열로 이번 문제를 풀어 보았다.
연구소 문제를 풀었을 당시에는 작동 원리에 대해서 긴가민가 했었는데 운 좋게 이번 문제를 접하면서 한번 더 공부 하게 될 수 있었다.
백 트래킹을 학습하지 않은 상태라 제대로 적용하지 못했는데 제대로 적용 할 수 있다면 코드가 더 깔끔 해질 것 같다.