티스토리 뷰
문제
https://www.acmicpc.net/problem/9202
알고리즘
트라이
풀이
격자판에서 주어진 문자열을 조건에 따라 찾아야 하는 문제입니다. 최대 점수, 찾은 단어의 개수, 가장 긴 단어를 구하기를 원하고 있습니다. 단어의 개수를 찾는 과정에서 최대 점수와 가장 긴 단어 또한 해결 가능하므로 단어를 찾는 것에 집중합시다.
격자판 위에서 단어를 탐색해야 하므로 DFS를 통해 일차적인 접근이 가능합니다. DFS연산량만 어림짐작해보면
(주어지는 보글의 수) X (4x4 격자판에서 DFS시작 가능한 위치의 개수) X (DFS의 깊이에 해당하는 단어의 길이) X
(각 알파벳마다 가능한 선택지의 수) 이고, 이는 대략 3천만에 가까운 숫자입니다. 즉 단어를 선형 시간 안에 찾지 않게 되면 시간 초과가 발생할 수 있으므로 트라이를 문제 해결을 위해 선택할 수 있습니다.
메모리 제한은 512MB입니다. 주어지는 단어의 수는 30만이고, 단어의 최대길이는 8, 알파벳 대문자의 갯수는 26개입니다. 즉 대략 249MB를 사용하므로 메모리 제한 안에 들어오게 됩니다. DFS과정에서 단어를 발견했다면 트라이의 위치만 보고 바로 단어에 접근하기 위해 map 자료구조와 이전에 발견한 단어인지 아닌지를 알기 위해 set를 추가적으로 사용했습니다.
코드
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define REP(i,n) for(int i=1;i<=n;++i)
#define FAST cin.tie(NULL);cout.tie(NULL); ios::sync_with_stdio(false)
using namespace std;
const int MAXC = 26;
const int MAXN = 300000;
const int dy[8] = { -1,-1,-1,0,0,1,1,1 };
const int dx[8] = { -1,0,1,-1,1,-1,0,1 };
const int score_board[9] = { 0,0,0,1,1,2,3,5,11 };
int cnt, w, b;
int ans, score;
int trie[MAXN][MAXC];
map<int, string> term;
char board[4][4];
bool visited[4][4];
string S;
set<int> SET;
void insert(string& s) {
int p = 0;
for (auto j : s) {
if (!trie[p][j - 'A'])
trie[p][j - 'A'] = ++cnt;
p = trie[p][j - 'A'];
}
term[p] = s;
}
bool inr(int y, int x) {
return 0 <= y && y < 4 && 0 <= x && x < 4;
}
void dfs(int y, int x, int p, int cur) {
visited[y][x] = true;
if (term.find(p) != term.end() && SET.find(p) == SET.end()) {
SET.insert(p);
++ans;
score += score_board[cur];
if (term[p].length() > S.length()) {
S = term[p];
}
else if (term[p].length() == S.length()) {
if (term[p] < S) S = term[p];
}
}
for (int i = 0;i < 8;++i) {
int ny = y + dy[i];
int nx = x + dx[i];
if (!inr(ny, nx)) {
continue;
}
int nxt = board[ny][nx] - 'A';
if (visited[ny][nx]) {
continue;
}
if (trie[p][nxt]) {
dfs(ny, nx, trie[p][nxt], cur + 1);
}
}
visited[y][x] = false;
}
int main() {
FAST;
cin >> w;
rep(i, w) {
cin >> S;
insert(S);
}
cin >> b;
while (b--) {
S = "";
SET.clear();
score = ans = 0;
rep(i, 4) rep(j, 4) cin >> board[i][j];
rep(i, 4) rep(j, 4) {
if (trie[0][board[i][j] - 'A']) {
dfs(i, j, trie[0][board[i][j] - 'A'], 1);
}
}
cout << score << ' ' << S << ' ' << ans << '\n';
}
return 0;
}
'Algorithm' 카테고리의 다른 글
[백준 3108] 로고 (0) | 2020.08.26 |
---|---|
[백준 2104] 부분 배열 고르기 (0) | 2020.08.18 |
[백준 5009] 유치원 (0) | 2020.08.15 |
[백준 16915] 호텔 관리 (0) | 2020.08.14 |
[백준 15675] 괴도 강산 (0) | 2020.08.13 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- sorting
- 이분탐색
- 2-SAT
- Segment tree
- 정렬
- 동적계획법
- 트라이
- dijkstra
- 좌표압축
- hld
- implementation
- Fenwick
- kmp
- knapsack
- sweeping
- 세그먼트트리
- Suffix Array
- spring
- greedy
- 이분매칭
- DP
- SCC
- union find
- 스위핑
- spring boot
- bfs
- Oracle
- 펜윅트리
- string
- dfs
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함