반응형
1. 각 점을 위치 벡터로 생각한다.
2. 점 A에서 B로 가는 벡터는 (B 위치 벡터) - (A 위치 벡터)이다.
3. 절반을 역벡터로 만든 뒤 모든 벡터를 합치면 벡터 매칭에 있는 벡터의 합을 구할 수 있다.
1. 각 점을 위치 벡터로 생각한다.
먼저 각 점을 위치 벡터로 생각해줄 것이다.
2. 점 A에서 B로 가는 벡터는 (B 위치 벡터) - (A 위치 벡터)이다.
다음과 같은 성질을 이용할 것이다.
두 점 A, B를 골라 A→B 또는 B→A로 가도록 벡터로 잇는 작업은, 두 점 A, B를 고른 뒤 두 점으로 가는 위치 벡터 중 하나를 역벡터로 만드는 작업이라고 할 수 있다.
3. 절반을 역벡터로 만든 뒤 모든 벡터를 합치면 벡터 매칭에 있는 벡터의 합을 구할 수 있다.
결국 구해야 하는 것은 벡터 매칭에 있는 백터들을 모두 합한 벡터이고, 따라서 벡터 매칭에 있는 N/2개의 벡터의 각 성분을 더하기만 하면 된다. 백터 매칭에 있는 각 벡터의 성분은 다음과 같은 두 벡터의 합으로 이루어져 있다.
- N개 점 중 한 점으로 가는 위치 벡터
- N개 점 중 한 점으로 가는 위치 벡터의 역벡터
따라서 최종 합벡터만 두고 보면 N개의 점으로 가는 위치벡터 중 절반만 역벡터로 만든 뒤 각 벡터의 성분을 모두 더한 것이 된다.
브루트포스로 절반을 역벡터로 만드는 모든 경우를 탐색한 뒤, 합벡터의 길이가 최소가 되는 경우를 찾으면 된다. N=20으로 매우 작으므로 O(2^N)으로도 시간 내에 돌아갈 수 있다.
반응형
import Foundation
let INF = 987654321.0
var N = 0
var points = Array(repeating: Vector(x: 0, y: 0), count: 20)
var minLength = INF
struct Vector {
let x: Int
let y: Int
var length: Double {
return sqrt(Double(x*x + y*y))
}
static func +(lhs: Vector, rhs: Vector) -> Vector {
Vector(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
static func -(lhs: Vector, rhs: Vector) -> Vector {
Vector(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
}
func sumAllVectors(bitmask: Int) -> Vector {
var sum = Vector(x: 0, y: 0)
for i in 0..<N {
if bitmask & (1 << i) == 0 {
sum = sum - points[i] // 마스킹된 N/2개 벡터는 역벡터 처리
} else {
sum = sum + points[i]
}
}
return sum
}
func bruteForce(index: Int, count: Int, bitmask: Int) { // 절반을 역벡터로 만든다. AB = OB - OA이기 때문
if index == N {
if count == N / 2 {
let sumVector = sumAllVectors(bitmask: bitmask)
minLength = min(minLength, sumVector.length)
}
return
}
if count < N/2 { bruteForce(index: index+1, count: count+1, bitmask: bitmask | (1 << index)) }
bruteForce(index: index+1, count: count, bitmask: bitmask)
}
func initTestcase() {
minLength = INF
}
func solution() {
var resultString = ""
var T = Int(readLine()!)!
while T > 0 {
initTestcase()
N = Int(readLine()!)!
for i in 0..<N {
let input = readLine()!.split(separator: " ").map{ Int(String($0))! }
let pair = Vector(x: input[0], y: input[1])
points[i] = pair
}
bruteForce(index: 0, count: 0, bitmask: 0)
resultString.write("\(minLength)\n")
T -= 1
}
print(resultString)
}
solution()
반응형
'Problem Solving > BOJ' 카테고리의 다른 글
백준 16724번 피리 부는 사나이 - 스위프트(Swift) 풀이 + 그림 설명 (0) | 2022.02.05 |
---|---|
백준 1766번 문제집 - C++(cpp) 풀이 (0) | 2022.02.04 |
백준 2342번 Dance Dance Revolution - 스위프트(Swift) 풀이 (0) | 2022.02.03 |
백준 2143번 두 배열의 합 - 스위프트(Swift) 풀이 (0) | 2022.02.03 |
백준 1644번 소수의 연속합 - 스위프트(Swift) 풀이 (0) | 2022.02.03 |
댓글