백트래킹
현재 상태에서 가능한 모든 선택지를 따라 들어가며 탐색하는 알고리즘
DFS와 헷갈릴 수도 있지만,
백트래킹 = DFS가 아니라 백트래킹 방법 중의 하나가 DFS인 것이다.
DFS는 깊이 우선 탐색으로 모든 경우의 수를 다 탐색하지만,
백트래킹은 조건에 맞지 않는다면 그 부분은 탐색하지 않고 탐색을 중지한 다음 그 이전으로 돌아가서 다른 경우를 탐색한다.
연습 문제
[백준`15649] N과 M (1)
문제
자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.
- 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열
입력
첫째 줄에 자연수 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)
출력
한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다.
수열은 사전 순으로 증가하는 순서로 출력해야 한다.
N = 4, M = 3일 때
첫 번째 원소를 1로 뒀을 때, 먼저 2를 쓰고 넘어간다.
1, 2가 채워진 리스트에서 사용 가능한 수는 3과 4
1, 2, 3을 넣고, 1, 2, 4를 넣으면 모든 칸이 차서 수열이 완성된 상태이기 때문에 출력해준다.
1, 2가 채워진 리스트에서는 할 수 있는 선택지를 다 했기 때문에 1만 채워진 리스트 상태로 되돌아간다.
두 번째 칸에 3을 넣은 상태로 넘어가면, 사용하지 않은 수는 2와 4니까 1, 3, 2와 1, 3, 4로 리스트를 채워준다.
백트래킹은 이런 식으로 돌아가게 된다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;
public class Main {
public static int[] arr;
public static boolean[] visited;
public static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
arr = new int[M];
visited = new boolean[N];
dfs(N, M, 0);
System.out.println(sb);
}
public static void dfs(int N, int M, int depth) {
// 재귀 깊이가 M이 되면 출력
if (depth == M) {
for (int num : arr) {
sb.append(num).append(' ');
}
sb.append('\n');
return;
}
for (int i = 0; i < N; i++) {
// 만약 해당 노드를 방문하지 않았다면
if (!visited[i]) {
visited[i] = true; // 방문 처리
arr[depth] = i + 1; // 해당 깊이 index에 i + 1값 저장
dfs(N, M, depth + 1); // 다음 자식 노드 방문
// 자식 노드 방문 끝나고 돌아오면 방문하지 않은 상태로 변경
visited[i] = false;
}
}
}
}
728x90
'알고리즘 > 문제 유형' 카테고리의 다른 글
자바 알고리즘 입출력 정리 [Java] (2) | 2024.11.04 |
---|---|
순열, 조합 파이썬으로 구현하기 (dfs) (0) | 2024.10.06 |
그리디(Greedy) 알고리즘 (0) | 2024.03.22 |
DP (Dynamic Programming) (1) | 2023.11.20 |
BFS / DFS (0) | 2023.11.10 |