Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 스택
- 백트래킹
- 빠른 입출력
- 시뮬레이션
- 그리디
- 이분 탐색
- 완전 탐색
- 비트마스크
- 피보나치 수
- 조합
- 클래스
- 큐
- 분할 정복
- 재귀
- 중복 순열
- lis
- 메모리풀
- 문자열
- 크루스칼
- BeautifulSoup
- 링크드리스트
- 순열
- 우선순위 큐
- 세그먼트 트리
- Knapsack
- dfs
- SSAFY
- BFS
- MST
- DP
Archives
- Today
- Total
작심 24/7
[백준] 9202번 Boggle 본문
9202번: Boggle
문제 상근이는 보드 게임 "Boggle"을 엄청나게 좋아한다. Boggle은 글자가 쓰여 있는 주사위로 이루어진 4×4 크기의 그리드에서 최대한 많은 단어를 찾는 게임이다. 상근이는 한 번도 부인을 Boggle��
www.acmicpc.net
단어 사전을 만들 때
트라이 알고리즘을 이용하여 트리를 만들면
트리 생성 시 O(L*M), 탐색 시 O(L)
(L : 제일 긴 문자열의 길이, M : 총 문자열의 수)
로 빠르게 문자열을 탐색할 수 있다.
Boggle 보드의 모든 칸마다
가로, 세로, 대각선으로 인접한 칸을 DFS로
글자 수 1부터 8까지 탐색한다.
탐색하면서 사전에 이 단어가 있는지 찾는데
해당 단어가 있다면
set에 있는 단어인지 체크해준 뒤
(중복 찾기 방지 위해)
set에 있는 단어이면 이미 찾았던 단어이므로 그냥 넘어가고
set에 없는 단어라면 처음 찾는 단어이므로
글자 수에 맞게 점수를 더하고 찾은 단어의 개수를 + 1 해준다.
자료 구조의 기본도 안 돼있는 상태에서
트라이를 구현하려니 너무 힘들었다.
클래스와 포인터의 기초부터 공부해서 겨우 풀었지만
보통 char형으로 구현하던데
char는 도저히 다루기 힘들어서
친숙하고 쉬운 string으로 푼 게 마음에 걸린다.
#include <iostream>
#include <cstring>
#include <set>
#include <algorithm>
#include <string>
using namespace std;
int N, B, len, word_cnt, res;
int dx[8] = { -1, -1, -1, 0, 0, 1, 1, 1 }, dy[8] = { -1, 0, 1, -1, 1, -1, 0, 1 }, score[9] = { 0, 0, 0, 1, 1, 2, 3, 5, 11 };
string word, a, longgest;
class Trie {
public:
Trie *node[26];
bool finish;
Trie() { // 멤버 변수 초기화
this->finish = false;
memset(node, NULL, sizeof(node));
}
void Insert(string key, int idx) {
if (key[idx] == NULL) finish = true; // 빈 문자열이면 끝난 문자열이므로 종료 노드로 지정
else {
int next = key[idx] - 'A';
if (node[next] == NULL) node[next] = new Trie(); // 현재 연결된 노드가 없는 경우 노드 생성
node[next]->Insert(key, idx + 1); // 다음 문자열로 넘어감
}
}
bool Find(string key, int idx) {
if (key[idx] == NULL) { // 문자열 끝까지 잘 탐색했을 때
if (finish) return true; // 찾는 문자열이 종료 노드면 찾기 성공
return false; // 종료 노드가 아니면 없는 문자열이므로 실패
}
int current = key[idx] - 'A';
if (node[current] == NULL) return false; // 생성되지 않은 노드가 존재하면 이 문자열은 없는 문자열이므로 실패
return node[current]->Find(key, idx + 1); // 다음 문자열로 넘어감
}
}trie;
set <string> s; // 중복 막기 위해
void Dfs(int X, int Y, string word, int cnt, string boggle[][5], bool visited[][5]) {
if (cnt == 9) return;
if (trie.Find(word, 0)) { // 현재 단어를 찾았고
if (s.find(word) == s.end()) { //현재 단어가 중복이 아니라면
s.insert(word); // 중복을 막아주기 위해 set 생성
word_cnt++, res += score[cnt];
if (longgest.size() < cnt) longgest = word;
else if (longgest.size() == cnt) longgest = min(longgest, word);
}
}
for (int i = 0; i < 8; i++) {
int x = X + dx[i], y = Y + dy[i];
if (x >= 0 && x < 4 && y >= 0 && y < 4 && !visited[x][y]) {
visited[x][y] = true;
word += boggle[x][y];
Dfs(x, y, word, cnt + 1, boggle, visited);
visited[x][y] = false;
word.resize(word.size() - 1);
}
}
}
int main() {
cin >> N;
for (int i = 0; i < N; i++) {
cin >> word;
trie.Insert(word, 0);
}
cin >> B;
for (int b = 0; b < B; b++) {
string boggle[5][5];
bool visited[5][5] = { false };
for (int i = 0; i < 4; i++) {
cin >> a;
for (int j = 0; j < 4; j++) boggle[i][j] = a[j];
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
visited[i][j] = true;
Dfs(i, j, boggle[i][j], 1, boggle, visited);
visited[i][j] = false;
}
}
cout << res << " " << longgest << " " << word_cnt << "\n";
res = 0, longgest = "", word_cnt = 0, s.clear();
}
return 0;
}
'백준' 카테고리의 다른 글
[백준] 17837번 새로운 게임 2 (0) | 2020.07.31 |
---|---|
[백준] 17779번 게리맨더링 2 (0) | 2020.07.29 |
[백준] 2042번 구간 합 구하기 (0) | 2020.07.23 |
[백준] 17143번 낚시왕 (0) | 2020.07.20 |
[백준] 16235번 나무 재테크 (0) | 2020.07.19 |
Comments