본문 바로가기
CS/Algorithm

9202 Boggle

by yongckim 2021. 11. 27.
728x90
반응형
문제 링크

https://www.acmicpc.net/problem/9202

 

9202번: Boggle

각각의 Boggle에 대해, 얻을 수 있는 최대 점수, 가장 긴 단어, 찾은 단어의 개수를 출력한다. 한 Boggle에서 같은 단어를 여러 번 찾은 경우에는 한 번만 찾은 것으로 센다. 가장 긴 단어가 여러 개

www.acmicpc.net

문제 접근

백트래킹 + 이분탐색을 이용하여 해결했습니다.

 

문제를 풀기 전 Boggle이라는 게임을 어떻게 하는 건지 알아야 하기 때문에 먼저 설명해보자면

 

Boggle은 4 x 4 크기의 알파벳이 적혀있는 게임판에서 최대한 많은 단어를 찾는 게임입니다.

 

단어를 만들때는 인접한 글자(가로, 세로, 대각선 방향)를 연결해서 만들 수 있으며, 이전에 사용한 위치는 다시 사용할 수 없습니다.

 

예를 들어 Hello라는 단어가 주어지고 다음과 같은 게임판이 주어졌다고 가정해봅시다.

boggle 게임판

다음 게임판에서 Hello의 단어라는 단어를 만들려면 다음과 같이 만들 수 있습니다.

저 같은 경우 각 알파벳의 위치마다 dfs를 이용하여 백트래킹시켜 모든 경우를 탐색하도록 구현하였습니다.

 

그리고 문제에 주어지는 단어의 수가 30만개 이므로 단어를 하나하나 비교하며 같은 단어가 있는지 확인하지 않고 이분탐색으로 맞는 단어가 있는지 빠르게 탐색할 수 있도록 하였습니다.

구현
import sys
input = sys.stdin.readline

boggle = []					# 게임판이 담길 리스트
ans = [0, 0]					# 정답이 담길 리스트(최대점수, 찾은 단어 개수)
dx = [0, 0, 1, -1, 1, -1, -1, 1] 		# 인접한 주사위로 이동하기 위해 사용하는 리스트(세로)
dy = [1, -1, 1 , -1, 0, 0, 1, -1] 		# 인접한 주사위로 이동하기 위해 사용하는 리스트(가로)
score = [0, 0, 0, 1, 1, 2, 3, 5, 11] 		# 정답 점수를 저장해 놓는 리스트
visit = [[] for _ in range(4)] 			# 방문 여부를 확인하는 리스트
w = int(input()) 				# 단어의 개수를 저장하는 변수
word = [input().rstrip() for x in range(w)] 	# 입력으로 주어지는 단어를 저장
input() 					# 공백을 입력받는 용도
b = int(input()) 				# 주어지는 게임판의 수
word.sort() 					# 입력받은 단어를 이분탐색하기 위해 미리 정렬해둠
useWord = [] 					# 해당 단어를 만들었었는지 확인하는 리스트
ans_string = "" 				# 찾은 단어중 가장 긴 문자열을 확인하는 문자열 변수

def safe(x, y):
	return x >= 0 and x < 4 and y >= 0 and y < 4
    
def bst(string):
	st = 0
	ed = w - 1
	while st <= ed :
		mid = (st + ed) // 2
		if word[mid] == string:
			return mid
		elif word[mid] < string:
			st = mid + 1
		else:
			ed = mid - 1
	return -1

def dfs(x, y, tmp):
	string = "".join(tmp)
	if (len(string) >= 9) :
		return
	search = bst(string)
	if search != -1:
		global ans_string
		if len(string) > len(ans_string):
			ans_string = string
		elif len(string) == len(ans_string) and string < ans_string:
			ans_string = string
		if useWord[search] == False:
			useWord[search] = True;
			ans[1] += 1
			ans[0] += score[len(string)]
	for i in range(8):
		nx = x + dx[i]
		ny = y + dy[i]
		if safe(nx, ny) and visit[nx][ny] == False:
			visit[nx][ny] = True
			tmp.append(boggle[nx][ny])
			dfs(nx, ny, tmp)
			tmp.pop()
			visit[nx][ny] = False


for i in range(b):
	boggle = []
	for _ in range(4):
		boggle.append(input().rstrip())
	if (i < b - 1):
		input()
	ans[0] = 0
	ans_string = ""
	ans[1] = 0
	tmp = []
	for j in range(4) :
		visit[j] = [False for _ in range(4)]
	useWord = [False for _ in range(w)]
	for x in range(4):
		for y in range(4):
			tmp.append(boggle[x][y])
			visit[x][y] = True
			dfs(x, y, tmp)
			visit[x][y] = False
			tmp.pop()
	print(ans[0], ans_string, ans[1])
반응형