반응형
🥺 이번엔 백트래킹 조지기
https://github.com/tony9402/baekjoon/tree/main/backtracking
해당 링크의 문제들을 도장깨기 하듯? 풀었고 풀이는 주석으로 달아두었습니다.
10971
https://www.acmicpc.net/problem/10971
💡왜 백트래킹인가?
순회에 필요한 비용을 행렬 형태로 주어지는데, 여기서 차례로 탐색하면서 소요되는 비용을 최소화하는 경우의 수가 너~무 많다.
내 풀이
import Foundation
let n = Int(readLine()!)!
var board:[[Int]] = []
var answer = Int(1e9)
var visited = Array(repeating: false, count: n)
// "한번 갔떤 도시로는 다시 갈 수 없다. -> 방문여부 표시"
for _ in 0..<n {
board.append(readLine()!.split(separator:" ").map { Int(String($0))! })
}
// 백트래킹
// N개의 도시는 무조건 거쳐서 다시 원래의 도시로 돌아옴
func dfs(_ sum: Int, _ depth: Int, _ cur: Int, _ start: Int){
if cur == start && depth == n { //n개의 도시를 거치고, start와 cur가 일치 -> 다시 원래의 도시로 돌아옴
answer = min(answer, sum)
return
}
for i in 0..<n { //visited[i]: 안간 도시만 가기
if !visited[i] && board[cur][i] != 0 { // board[cur][i] : cur에서 i로 갈 때의 비용
visited[i] = true // cur를 i로 -> i 도시 탐색
dfs(sum+board[cur][i], depth+1, i, start)
visited[i] = false
}
}
}
dfs(0, 0, 0, 0)
print(answer)
14888
https://www.acmicpc.net/problem/14888
💡왜 백트래킹인가?
연산자를 조합해서 최대, 최소값을 구해야하는데 완전탐색으로 구하기에는 경우의수가 너무 많다.
내 풀이
import Foundation
let n = Int(readLine()!)!
let arr = readLine()!.split(separator:" ").map { Int($0)! }
var operator_count = readLine()!.split(separator:" ").map { Int($0)! }
var minValue = 1000000000 // 최소, 최대값 설정할 때 범위를 잘 볼것
var maxValue = -1000000000 // 최소, 최대값은 -10억 ~ 10억 사이
func dfs(_ depth:Int, _ result:Int) {
if depth == n { // 숫자의 개수가 n일때
minValue = min(result, minValue)
maxValue = max(result, maxValue)
return
}
for i in 0..<operator_count.count {
if operator_count[i] > 0 { // 연산자의 개수가 아직 남아있는 경우
operator_count[i] -= 1 // 연산자 사용하는걸로 했다가
switch i {
case 0:
dfs(depth+1, result+arr[depth])
case 1:
dfs(depth+1, result-arr[depth])
case 2:
dfs(depth+1, result*arr[depth])
default:
dfs(depth+1, result/arr[depth])
}
operator_count[i] += 1 // 다시 안하는걸로 가지치기
}
}
}
dfs(1, arr[0]) // 처음수부터 입력인자로 넣기
print(maxValue)
print(minValue)
14889
https://www.acmicpc.net/problem/14889
내 풀이
import Foundation
let n = Int(readLine()!)! //짝수 -> 절반으로 나눠야함
var board:[[Int]] = []
for _ in 0..<n {
board.append(readLine()!.split(separator:" ").map { Int($0)! })
}
// 완탐 or 백트래킹? -
var visited = Array(repeating: false, count:n)
var minValue = Int(1e9)
var star = 0, link = 0
func backtracking(_ depth: Int, _ idx: Int) {
if depth == n/2 { // n/2로 좁힌 이유 -> 어차피 절반 뽑으면 나머지 절반은 자동 구성이기 때문
star = 0
link = 0
for i in 0..<n {
for j in 0..<n {
if visited[i] && visited[j] {
star += board[i][j] + board[j][i] // i와 j의 능력치 둘다 더해줘야함
}
if !visited[i] && !visited[j] {
link += board[i][j] + board[j][i]
}
}
}
minValue = min(minValue, abs(star-link)/2) // i 와 j - j와 i가 겹치므로 /2를 해줘야함
return
}
for i in idx..<n { // 순열이 아니라 조합이라고 생각하면 13이나 31이나 같으므로 idx부터 시작 (그전은 볼 필요 X)
if !visited[i] {
visited[i] = true
backtracking(depth+1, i+1) // 한명 인원 더 선발하기 (그 전은 볼 필요 없으므로)
visited[i] = false
}
}
}
backtracking(0, 0)
print(minValue)
반응형
'⚙️ 알고리즘 > 백준' 카테고리의 다른 글
[백준/Python] 숨바꼭질 1, 3 정리 (feat. 0-1 BFS, 다익스트라) (0) | 2023.08.11 |
---|---|
[백준/Swift] 1520 내리막길 (0) | 2023.07.27 |
[Swift] 백준 가장 긴 증가하는 부분 수열(LIS), 최장 공통 부분 수열(LCS) 관련 문제풀이 (0) | 2023.06.01 |
[Swift] 백준 20208 - 진우의 민트초코우유 (0) | 2023.05.08 |
[Swift] 백준 21921 - 블로그 (0) | 2023.04.25 |