티스토리 뷰

Problem Solving/BOJ

[Python3] 백준 - 9997 폰트

dev.hunmin 2021. 1. 25. 01:02
728x90

www.acmicpc.net/problem/9997

 

9997번: 폰트

첫째 줄에 단어의 개수 N (1 ≤ N ≤ 25)가 주어진다. 다음 N개 줄에는 사전에 포함되어있는 단어가 주어진다. 단어의 길이는 100을 넘지 않으며, 중복되는 단어는 주어지지 않는다.

www.acmicpc.net

- 접근법

N이 25이므로 브루트포스로 모든 단어를 조합해도 O(2^25)로 가능하다.

그러나 탐색과 연산횟수도 합해진다면 O(2^25*alpha)로 TLE가 날수있으므로 가지치기를 잘해줘야한다.

 

사실 이 문제는 비트마스킹으로 해당 알파벳이 존재하면 TRUE, 안하면 FALSE같이 저장해서 간단히 비트연산으로 알파벳 26개 다 존재하는지 볼 수 있다.

하지만 나는 당시에 파이썬으로 비트마스킹하는법을 몰라서 처음에 단어들을 받을때 먼저 set화 시켜놓고 set끼리의 연산으로 비트마스킹을 흉내냈는데 빠른 시간에 accept되는것을 보니 set연산은 시간을 많이 잡아먹진 않는 것 같다. 

 

따라서 다시 이 문제를 요약하자면

"각 단어들을 (사용해서 문장에 붙일 때, 안 붙일 때)로 탐색하면서 현재 문장이 a부터z까지 모든 요소가 있는지 검사만 해주면 된다."

"index 끝까지 탐색하고 검사하는 것보다는, 성능을 더 올리기 위해 가지치기를 해주자"

 


- 소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import sys
input=sys.stdin.readline
global answer
answer=0
def word_combine(vertex,sentence) :
    if len(sentence) == 26:
        global answer
        answer += 2 ** (N - vertex-1)
        return
    if vertex>=0 and len(sentence)+word_len[vertex]<26 :
        return
    if vertex==N-1 :
        return
    word_combine(vertex+1,sentence|word_list[vertex])
    word_combine(vertex+1,sentence)
 
N=int(input().rstrip())
word_list=[set(input().rstrip()) for x in range(N)]
word_len=[len(sets) for sets in word_list]
for i in range(N-2,-1,-1) :
    word_len[i]+=word_len[i+1]
word_combine(-1,set())
print(answer)
cs
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함