본문 바로가기

알고리즘/백준 문제 풀이

[Python] 2418번 단어 격자

728x90

 

 

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


 

24/11/14

 

 

예전에 북마크 해뒀다가 지금 해결한 문제다. 해결 방식은 어제 해결했던 내리막길 문제와 유사하다.


 

문제 접근 방식:

 

 

탑다운 DP로 접근했다.

 

DP상태는 다음과 같이 정의했다.

 

DP[i][j][k] = 지금까지 단어에서 k번째 글자까지 읽었고, (i, j)에 위치한 글자가 단어에서 k번째 글자일 때, 단어를 읽을 수 있는 방법의 수

 

이후, 모든 격자 칸을 조사하며, 이 격자 칸에 적힌 글자가 단어의 첫 글자와 일치한다면, 즉, (i, j)에 위치한 글자가 단어의 0번째 글자라면 DP[i][j][0] = 1로 초기화 해주었다.

 

이후 dfs를 통해 주변 8방향을 조사하며 구현했다.

 

우리가 원하는 값은 단어의 마지막 글자와 (i, j)에 위치한 글자가 일치할 때의 DP값들을 전부 더한 것이므로, 조건을 만족할 때 dfs를 돌렸다. 


아래는 내가 위의 접근 방식과 같이 작성한 파이썬 코드이다. 더보기를 누르면 확인할 수 있다.

더보기
# 2418번 단어 격자
# DP
'''
접근 방법:
DP[i][j][k] = (i,j)에 위치한 글자가 k번째 글자일 때 단어를 읽을 수 있는 방법의 경우의 수
탑다운으로 해결해보자.
'''
import sys
input = sys.stdin.readline
sys.setrecursionlimit(500_000)

H, W, L = map(int, input().split())
G = [list(input().rstrip()) for _ in range(H)]
DP = dict()
dr, dc = [-1, -1, -1, 0, 0, 1, 1, 1], [-1, 0, 1, -1, 1, -1, 0, 1]
word = input().rstrip()
# DP값 초기화
for i in range(H):
    for j in range(W):
        if G[i][j] == word[0]:
            DP[(i, j, 0)] = 1
def dfs(i, j, k):
    if (i, j, k) in DP:
        return DP[(i, j, k)]
    A = 0
    if k == 0: return 0
    for t in range(8):
        ni, nj = i+dr[t], j+dc[t]
        if 0 <= ni < H and 0 <= nj < W and G[ni][nj] == word[k-1]:
            if (ni, nj, k-1) not in DP:
                dfs(ni, nj, k-1)
            A += DP[(ni, nj, k-1)]
    DP[(i, j, k)] = A
    return DP[(i, j, k)]
ans = 0
for i in range(H):
    for j in range(W):
        if G[i][j] == word[-1]:
            ans += dfs(i, j, L-1)
print(ans)

'알고리즘 > 백준 문제 풀이' 카테고리의 다른 글

[Python] 32612번 Expected Eyes  (0) 2024.11.16
[Python] 1178번 간선 추가  (0) 2024.11.15
[Python] 1520번 내리막 길  (0) 2024.11.13
[Befunge] 2380번 Star  (0) 2024.11.12
[Python] 32645번 동까뚱뽭 게임  (0) 2024.11.11