=> 그러나.. 당연히 위와 아래를 동시 탐색해서 사다리를 설치하는 방식은, 결국 중간에만 다리를 설치할 수 있기에 불가능한 로직이었음
재귀에서 가장 중요한 건, 종료조건 설정!!!
해당 유형 문제를 풀 때는 종료조건 설정 -> 큰 틀 잡기 -> 예외처리 순서대로 진행해보자.
생각보다 내가 큰 틀 잡기에 집중하느라 이걸 놓치는 것 같다.
import java.io.*;
import java.util.*;
public class Main {
static int N; // 세로선 개수
static int M; // 기존 가로선 개수
static int H; // 가로선 높이 개수
static boolean[][] hasBridge; // hasBridge[row][col] : row 높이에서 col과 col+1 연결 여부
static int answer = -1;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
H = Integer.parseInt(st.nextToken());
hasBridge = new boolean[H + 1][N + 1];
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int row = Integer.parseInt(st.nextToken()); // 높이
int col = Integer.parseInt(st.nextToken()); // 세로선 번호
hasBridge[row][col] = true;
}
// 0~3개 추가 시도
for (int maxAdd = 0; maxAdd <= 3; maxAdd++) {
if (dfs(0, maxAdd)) {
answer = maxAdd;
break;
}
}
System.out.println(answer);
}
static boolean dfs(int addedCount, int maxAdd) {
if (addedCount == maxAdd) {
return isValidLadder();
}
for (int row = 1; row <= H; row++) {
for (int col = 1; col < N; col++) {
if (hasBridge[row][col]) continue;
// 왼쪽 인접 체크
if (col > 1 && hasBridge[row][col - 1]) continue;
// 오른쪽 인접 체크
if (col < N - 1 && hasBridge[row][col + 1]) continue;
hasBridge[row][col] = true;
if (dfs(addedCount + 1, maxAdd)) return true;
hasBridge[row][col] = false;
}
}
return false;
}
static boolean isValidLadder() {
for (int startLine = 1; startLine <= N; startLine++) {
int currentLine = startLine;
for (int row = 1; row <= H; row++) {
if (currentLine < N && hasBridge[row][currentLine]) {
currentLine++;
}
else if (currentLine > 1 && hasBridge[row][currentLine - 1]) {
currentLine--;
}
}
if (currentLine != startLine) return false;
}
return true;
}
}