문제 링크: https://www.acmicpc.net/problem/14889
14889번: 스타트와 링크
예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.
www.acmicpc.net
문제 풀이는 쉬웠다고 생각합니다.
하지만 시간복잡도를 줄이는데에 있어서 많이 힘들었습니다.
package sixteenthDay
import java.io.*
import java.util.*
fun main(){
val br = BufferedReader(InputStreamReader(System.`in`))
val n = br.readLine().toInt()
var valueArr = Array(n+1){Array(n+1){0} } // 입력받은 점수
repeat(n){ // 점수 각각 2차원 배열에 추가
val string = StringTokenizer(br.readLine())
for (index in 1..n){
valueArr[it+1][index] = string.nextToken().toInt()
}
}
val visit = Array(n+1){false} // 방문 배열
val ans = Array(n){0} //숫자를 뽑아서 저장할 배열
var finalValue = Int.MAX_VALUE //최소값을 저장할 변수
fun dfs(num: Int){
if (num == n){
var start = 0
var link = 0
// 배열의 0번 째부터 n/2 까지는 link 계산
// 나머지는 start 계산
for (index in 0 until n/2){
for (index1 in index+1 until n/2){
link += valueArr[ans[index+n/2]][ans[index1+n/2]] + valueArr[ans[index1+n/2]][ans[index+n/2]]
start += valueArr[ans[index]][ans[index1]] + valueArr[ans[index1]][ans[index]]
}
}
// 두 절대값을 뺀 값
val v = Math.abs(start - link)
// 0일 때는 출력 후 종료
if (finalValue == 0){
println(0)
System.exit(0)
}
// 이전 값보다 작으면 저장
if (finalValue >= v)
finalValue = v
return
}
for (index in 1 ..n){
if (!visit[index]){
visit[index] = true
ans[num] = index
dfs(num+1)
visit[index] = false
}
}
}
dfs(0)
println(finalValue)
}
답안은 맞은 것 같았지만, 시간초과가 계속해서 떴습니다.
계속 시도해보다, 결국은 다른 분의 코드를 참고하게 되었습니다.
package Any
import java.io.*
import java.util.*
fun main(){
val br = BufferedReader(InputStreamReader(System.`in`))
val n = br.readLine().toInt()
val arr = Array(n+1){Array(n+1){0} }
repeat(n){i ->
val token = StringTokenizer(br.readLine())
for (index in 1..n){
arr[i+1][index] = token.nextToken().toInt()
}
}
val v = Array(n+1){false}
var min = Int.MAX_VALUE
fun dfs(num: Int, idx: Int){
if (num == n/2){
var teamStart = 0
var teamLink = 0
for (index in 1 until n){
for (index1 in index+1..n){
if (v[index] && v[index1]){ //방문한 값들은 start
teamStart += arr[index][index1] + arr[index1][index]
}
else if (!v[index] && !v[index1]){ // 방문하지 않은 것들은 link
teamLink += arr[index][index1] + arr[index1][index]
}
}
}
val diff = Math.abs(teamStart-teamLink)
if (diff==0){
println(0)
System.exit(0)
}
min = Math.min(diff,min)
return
}
for (index in idx..n){
if (!v[index]){
v[index] = true
dfs(num+1, index+1)
v[index] = false
}
}
}
dfs(0, 1)
println(min)
}
다른 분의 코드를 확인해보고 나서야 제 코드가 비효율적이라는 것을 깨달았습니다.
예를 들어 N이 4일 때,
1 2 3 4, 1 2 4 3 ... 등 결과는 같지만, 중복되는 경우의 수가 많이 계산됩니다.
제 스스로 해내지 못해 기분이 좋지 않았습니다.
답안 코드를 따라 작성해보면서 백트래킹의 원리에 대해 다시 공부해보는 시간을 가졌습니다.
'알고리즘 > 매일마다 풀기(백준)' 카테고리의 다른 글
[2023-04-18] 1463 영화 감독 숌(Kotlin) + 1문제 (0) | 2023.04.18 |
---|---|
[2023-04-17] 16139 인간 - 컴퓨터 상호작용(Kotlin) + 2문제 (0) | 2023.04.17 |
[2023-04-15] 1461 도서관 (Kotlin) + 1문제 (0) | 2023.04.15 |
[2023-04-14] 1041 주사위(Kotlin) (0) | 2023.04.14 |
[2023-04-13] 14888 연산자 끼워넣기 + 6문제 (0) | 2023.04.13 |
댓글