Algorithm
[Swift 백준] 15649 N과 M (1)
Kim Roks
2025. 1. 8. 19:28
저도 백트래킹은 처음이라 백트래킹의 개념에 대해 먼저 짚어보면 다음과 같습니다.
백트래킹의 핵심
- DFS(깊이 우선 탐색)를 기반으로 합니다.
- 탐색 중, 조건에 맞지 않는 경우를 가지치기(pruning)하여 탐색 범위를 줄입니다.
- 탐색이 끝난 후, 상태를 이전으로 복원(backtracking)합니다.
풀이 아이디어는 다음과 같습니다.
- DFS를 이용해 깊이 우선으로 탐색:
- M 길이에 도달할 때까지 가능한 숫자를 하나씩 추가.
- 가지치기:
- 이미 선택한 숫자는 다시 선택하지 않음.
- 상태 복원:
- 재귀 호출 후, 선택했던 숫자를 제거하고 이전 상태로 되돌아감.
풀이 코드는 아래와 같습니다.
풀이
let nm = readLine()!.split(separator: " ").map { Int($0)! }
let (n, m) = (nm[0], nm[1])
var resultArr = [Int]() // 현재까지 선택된 숫자를 저장하는 배열
func dfs() {
if resultArr.count == m {
// 조건을 만족하면 결과 출력
print(resultArr.map { String($0) }.joined(separator: " "))
return
}
for i in 1...n {
if !resultArr.contains(i) { // 중복 방지
resultArr.append(i) // 숫자를 추가
dfs() // 다음 단계로 탐색
resultArr.removeLast() // 상태 복원
}
}
}
dfs() // 탐색 시작
보통 재귀를 통해 풀이하는거 같더라고요
하지만 저는 재귀가 유독 가독성이 떨어진다고 생각해서 아래는 배열을 통해 풀이해보았습니다.
let nm = readLine()!.split(separator: " ").map { Int($0)! }
let (n, m) = (nm[0], nm[1])
var queue: [(current: [Int], depth: Int)] = []
queue.append(([], 0))
while !queue.isEmpty {
let (current, depth) = queue.removeFirst()
if depth == m {
print(current.map { String($0) }.joined(separator: " "))
continue
}
for i in 1...n {
if !current.contains(i) {
queue.append((current + [i], depth + 1))
}
}
}
보통 dfs에선 stack을 사용하는게 일반적이라 removeLast를 사용하겠지만, 임의로 변경해봤습니다.(for문에서 reversed를 쓰고싶지 않았음)
정석적인 풀이는 아니지만 이런 방식으로도 풀 수 있습니다!