Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
31 |
Tags
- AppArmor
- Prefix sum
- Linux
- 스프링
- 부팅 장애 대응
- 너비우선탐색
- 슬라이딩 윈도우
- bitmasking
- 로그 수집
- 네트워크 관리 및 진단
- git
- 스프링부트
- 브루트포스
- 알고리즘
- 깃허브
- SlidingWindow
- 비트마스킹
- 깊이우선탐색
- 깃
- 리눅스
- TwoPointer
- 누적합
- 투포인터
- httpmessageconverter
- REST API
- 다이나믹 프로그래밍
- Spring Boot
- github
- spring
- 분할정복
Archives
- Today
- Total
kimgusxo 님의 블로그
백트래킹(Backtracking) 본문
1. 백트래킹(Backtracking)이란?

- 백트래킹은 문제의 가능한 모든 해를 탐색하는 과정에서 조건을 만족하지 않는 경로를 조기에 포기하여 탐색 범위를 줄이는 기법이다.
- 그리디나 단순 브루트포스와 달리 백트래킹은 모든 배치를 시도하지만 조건을 위반하는 경우 탐색을 중단하고 되돌아간다.
1-1. 핵심 아이디어
- 문제 분할: 문제를 여러 하위 문제로 나눈 후 각 단계에서 선택할 수 있는 후보를 탐색한다.
- 가지치기: 현재까지의 선택이 문제의 조건을 만족하는지 검사하고 만족하지 않으면 바로 이전 상태로 돌아가 다른 후보를 탐색한다.
1-2. 백트래킹 장단점
- 장점: 문제의 해 공간이 크더라도 불필요한 경로를 빠르게 배제한다, 복잡한 문제도 재귀 호출과 조건 검사를 통해 간결한 코드로 구현 가능하다.
- 단점: 최악의 경우 모든 경우를 탐색한다, 문제에 따라 최적화방법이 결합되지 않으면 비효율적일 수 있다.
2. 백트래킹 활용 문제
2-1. N-Queen 문제
- N x N 체스판위에 N개의 퀸을 서로 공격하지 않도록 놓는 문제이다.
- 퀸은 같은 행, 열, 대각선 상에 있을 때 서로 공격할 수 있다.
public class NQueen {
// 모든 해의 가짓수를 전역 변수로 관리
static int count = 0;
// 현재 위치에 퀸을 놓을 수 있는지 체크하는 함수
public static boolean isSafe(int[][] board, int row, int col, int n) {
// 같은 열에 있는 퀸 검사 (위쪽만 확인)
for(int i = 0; i < row; i++) {
if(board[i][col] == n) {
return false;
}
}
// 왼쪽 대각선 위쪽 검사
for(int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if(board[i][j] == n) {
return false;
}
}
// 오른쪽 대각선 위쪽 검사
for (int i = row, j = col; i >= 0 && j < n; i--, j++) {
if (board[i][j] == 1) {
return false;
}
}
return true;
}
// 백트래킹을 이용해 N-Queen 문제의 모든 해를 탐색하는 함수
public static void solveNQueen(int[][] board, int row, int n) {
// 기저 조건: 모든 행에 퀸을 놓았다면 해를 찾은 것
if(row == n) {
count++;
return;
}
// 현재 행의 모든 열에 대해 퀸 놓기
for(int col = 0; col < row; col++) {
if(isSafe(board, row, col, n)) {
board[row][col] = 1; // 퀸 놓기
solveNQueen(board, col+1, n); // 다음행으로 진행
board[row][col] = 0; // 백트래킹: 놓은 퀸 제거
}
}
}
public static void main(String[] args) {
// 예제 데이터
int n = 4;
int[][] board = new int[n][n];
solveNQueen(board, 0, n);
System.out.println(count);
}
}
2-2. Word Search 문제
- 주어진 2차원 보드에서 특정 단어가 존재하는지 확인하는 문제이다.
- 단어는 인접(상하좌우)한 칸들로 연결되어야 하며, 같은 칸을 두 번 이상 사용할 수 없다.
public class WordSearch {
// 4방향 이동: 위, 오른쪽, 아래, 왼쪽
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
// 주어진 보드에서 단어가 존재하는지 확인하는 함수
public static boolean exist(char[][] board, String word) {
int rows = board.length;
int cols = board[0].length;
boolean[][] visited = new boolean[rows][cols];
// 보드의 모든 칸을 시작점으로 DFS 돌리기
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
if(dfs(board, word, 0, i, j, visited)) {
return true;
}
}
}
return false;
}
// DFS로 board[x][y]에서 시작하여 단어의 index번째 문자부터 탐색
private static boolean dfs(int[][] board, String word, int index, int x, int y, boolean[][] visited) {
// 기저 조건: 단어의 모든 문자를 찾은 경우
if(index == word.length()) {
return true;
}
// 범위 체크, 방문 여부, 현재 문자 일치 여부 확인
if (x < 0 || x >= board.length || y < 0 || y >= board[0].length || visited[x][y] || board[x][y] != word.charAt(index)) {
return false;
}
// 현재 칸 방문 처리
visited[x][y] = true;
// 4방향(상, 우, 하, 좌) 탐색
for (int dir = 0; dir < 4; dir++) {
int newX = x + dx[dir];
int newY = y + dy[dir];
if (dfs(board, word, index + 1, newX, newY, visited)) {
return true;
}
}
// 백트래킹: 현재 칸 방문 취소
visited[x][y] = false;
return false;
}
public static void main(String[] args) {
// 예제 데이터
char[][] board = {
{'A', 'B', 'C', 'E'},
{'S', 'F', 'C', 'S'},
{'A', 'D', 'E', 'E'}
};
String word = "ABCCED";
boolean result = exist(board, word);
// 출력: true
System.out.println(result);
}
}
'Algorithm' 카테고리의 다른 글
비트마스킹(Bitmasking) (0) | 2025.04.28 |
---|---|
분할정복(Divide and Conquer) (0) | 2025.04.08 |
깊이 우선 탐색(DFS) (0) | 2025.03.22 |
너비 우선 탐색(BFS) (0) | 2025.03.22 |
그리디(Greedy) (0) | 2025.03.19 |