알고리즘/문제풀이
[BOJ] 18428 감시 피하기 (Java)
세동세
2024. 10. 8. 12:39
문제 링크
https://www.acmicpc.net/problem/18428
문제 이해
선생님과 학생이 존재하는데, 선생님이 학생을 잡는 문제이다.
장애물이 존재하면, 선생님은 학생을 볼 수 없다.
임의의 3개 장애물이 존재하고 3개의 장애물을 설치해서 선생님이 학생을 잡을 수 없는 케이스가 존재하면 YES / 무조건 잡히는 케이스이면 NO를 출력한다.
백트래킹 혹은 장애물 3개를 인지하면 쉽게 풀 수 있는 문제다.
자바로 풀면서 백트래킹으로 풀었지만, 내가 파이썬으로 코테를 풀었다면 N*N의 mapSize가 크지 않았기 때문에 조합으로 맵을 구해두고
BFS 돌려서 탐색했을 것 같다.
나는 백트래킹으로 장애물을 3개 설치가 끝나면, catchableStudent 함수를 실행한다.
catchableStudent는 선생님의 시야에서 학생을 잡을 수 있는지 여부를 확인한다 (4방향 모두 탐색)
학생을 찾는 과정은 재귀로 돌렸다.
일반적인 DFS/BFS/백트래킹으로 쉽게 풀렸던 문제!
코드
package BOJ;
import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
/**
* BOJ_18428_감시피하기
* */
public class BOJ_18428_감시피하기 {
static BufferedReader br;
static StringTokenizer st;
static int mapSize;
static char [][] map;
static int[] deltaRow = {-1, 0, 1, 0};
static int[] deltaCol = {0, -1, 0, 1};
static ArrayList<Point> teacherList;
// 지역으로 사용하는 전역 변수
static int count;
static String result;
private static boolean inMap(int row, int col) {
return row >= 0 && row < mapSize && col >= 0 && col < mapSize;
}
private static void findStudent(Point point, int direction) {
// 만약 맵 밖으로 나가면 종료
if (!inMap(point.x, point.y)) {
return;
}
// 벽이면 더 이상 탐색을 종료
if (map[point.x][point.y] == 'O') {
return;
}
// 학생을 찾았다면
if (map[point.x][point.y] == 'S') {
// 만약 이미 카운팅 한것이면
count += 1;
}
int nextRow = point.x + deltaRow[direction];
int nextCol = point.y + deltaCol[direction];
findStudent(new Point(nextRow, nextCol), direction);
return;
}
private static boolean catchableStudent() {
// 선생님이 학생을 찾는다
count = 0;
// 선생님 입장에서 학생 레이더를 찾는다 (횟수는 중복 포함)
for (Point teacher : teacherList) {
// 4방향 dfs(찾기)
for (int direction = 0; direction < 4; direction ++) {
findStudent(teacher, direction);
}
}
if (count == 0) {
return false; // 잡을 수 없는 게 있으면
}
return true; // 잡는 경우
}
private static void makeMap(int wall) {
if (wall == 3) {
// 탐색
if (!catchableStudent()){
result = "YES"; // 잡을 수 없다!
}
return;
}
// wall 세우기
for (int row = 0; row < mapSize; row ++) {
for (int col = 0; col < mapSize; col ++) {
if (map[row][col] == 'X') {
map[row][col] = 'O'; // 넣기
makeMap(wall + 1);
map[row][col] = 'X'; // 다시 풀기
}
}
}
}
public static void main(String[] args) throws IOException {
br = new BufferedReader(new InputStreamReader(System.in));
mapSize = Integer.parseInt(br.readLine().trim());
teacherList = new ArrayList<>();
// 입력
map = new char[mapSize][mapSize];
for (int row = 0; row < mapSize; row ++) {
st = new StringTokenizer(br.readLine().trim());
for (int col = 0; col < mapSize; col ++) {
map[row][col] = st.nextToken().charAt(0);
if (map[row][col] == 'T') {
teacherList.add(new Point(row, col));
}
}
}
result = "NO"; // 결과물
// 장애물 설치 3개
makeMap(0);
System.out.println(result);
}
}