본문 바로가기
Algorithm/문제풀이_백준

[Swift][비트마스킹] 백준 1062번 (가르침)

by Joahnee 2022. 5. 11.

요구능력

조합, 비트마스킹

 

문제풀이

나혼자 처음에 이해를 못한건가 싶기도한데..

anta tica를 기본으로 깔고 중간에 있는 단어들중에서 k개를 배운다는줄 알았다.

그게 아니고 anta tica포함 k개였다.

 

C++언어로는 완탐조합만 돌려도 시간초과가 나오지 않을것이다.

하지만, 스위프트로 풀기위해서는 비트마스킹을 사용해야한다.

 

1) 문장을 입력받을 때 각 문장마다 단어를 비트마스킹으로 추가해줬다.

for i in 0..<n{
    let a = readLine()!.map{String($0)}
    for j in a{
        wordsBit[i] |= 1 << (Int(Character(j).asciiValue! - Character("a").asciiValue!))
    }
}

 

2) k가 5보다 작게 들어오면 anta tica마저 배우지 못하기 때문에 읽을 수 있는 단어개수가 0개이다.

그래서 0을 리턴해줬고,

비트마스킹을 사용해서 alphabet에 읽을 수 있는 단어들을 저장해 줄 것이다.

그리고 k에서는 antic를 추가했으니 5를 빼준다.

func solution() -> Int{
    if k < 5{
        return 0
    }
    alphabet |= 1 << (Int(Character("a").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("n").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("t").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("i").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("c").asciiValue! - Character("a").asciiValue!))
    k = k - 5
    dfs(0, 0)
    
    return result
}

 

3)  조합을 사용했다.

어차피 사용할 수 있는 알파벳은 순서가 필요없기 때문이다.

 

func dfs(_ depth: Int, _ start: Int){
    var count = 0
    if depth == k{
        for i in 0..<n{
            if wordsBit[i] & alphabet == wordsBit[i]{
                count += 1
            }
        }
        result = max(result, count)
        return
    }
    for i in start...25{
        if (alphabet & (1 << i)) == 0{
            alphabet |= (1 << i)
            dfs(depth + 1, i)
            alphabet &= ~(1 << i)
        }
    }
}

 

후기

처음에 조합으로 그냥 완탐돌았다가 시간초과나서.. 비트마스킹에 대해 공부해보는 좋은시간을 가진것같다.

언제 비트마스킹을 사용해야되는건지는.. 아직감이 안잡혀서 코테에서는 아직 못쓸거같다.

 

코드

import Foundation
var nk = readLine()!.split(separator: " ").map{Int(String($0))!}
let n = nk[0]
var k = nk[1]
var result = 0
var alphabet = 0
var wordsBit = Array(repeating: 0, count: 50)
for i in 0..<n{
    let a = readLine()!.map{String($0)}
    for j in a{
        wordsBit[i] |= 1 << (Int(Character(j).asciiValue! - Character("a").asciiValue!))
    }
}
func dfs(_ depth: Int, _ start: Int){
    var count = 0
    if depth == k{
        for i in 0..<n{
            if wordsBit[i] & alphabet == wordsBit[i]{
                count += 1
            }
        }
        result = max(result, count)
        return
    }
    for i in start...25{
        if (alphabet & (1 << i)) == 0{
            alphabet |= (1 << i)
            dfs(depth + 1, i)
            alphabet &= ~(1 << i)
        }
    }
}
func solution() -> Int{
    if k < 5{
        return 0
    }
    alphabet |= 1 << (Int(Character("a").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("n").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("t").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("i").asciiValue! - Character("a").asciiValue!))
    alphabet |= 1 << (Int(Character("c").asciiValue! - Character("a").asciiValue!))
    k = k - 5
    dfs(0, 0)
    
    return result
}

print(solution())

댓글