이 글은 BFS/DFS에 대한 저의 이해를 기록한 글 입니다. 사람마다 이해하는 방법이 다를 수 있으니, 너그러운 시선으로 봐주세요! 대신, 틀린 부분이 있다면, 거침없이 지적/tackle해주세요 !
경로 찾기 문제
- 알고리즘 문제를 풀다보면 , BFS 관련해서 자주 등장하게 되는게 , 길찾기 문제이다. 이 길찾기 문제에 대해서, 하나하나 뜯어볼 생각이다.
왜 BFS,DFS는 경로 찾기 문제에 쓰일까
- 당연하다. BFS, DFS는 완전 탐색 알고리즘 중, 하나이고 모든 경우의 수를 보는 알고리즘이기 때문에, 답을 못찾을 수가 없다고 말하면 알고리즘을 배우는 의미가 없으니까 , 말해주면 길찾기 문제의 Map을 그래프 관계로 나타낼 수 있고, 이 배열을 하나하나 다 순회하면서 탐색하는것보단, BFS,DFS로 쭊쭊 퍼져가면서 탐색하는게 훨씬 효율적이기 때문.
경로를 찾는 Map 표현하는 방법
- 보통 BFS 문제를 보면 아래와 같이 , 0과 1 혹은 , 0,*,$,# 등등 다양한 요소로 길을 진행하는데 방해하는 요소들(벽,불,물,돌 등)을 2차원맵에 표현하게 된다.
밑은 '0'은 벽이고 ,'1'은 지나갈 수 있는 통로라고 생각해보자. 그럼, 빨간선을 따라, 우리는 길을 찾아가게 될거다.
여기서, BFS,DFS를 쓰려고하면, 막막할 것이다. "내가 아는 BFS,DFS는 우선 인접행렬/인접리스트로 표현이 되어야만, BFS,DFS를 사용할 수 있는데.." 엄밀히 말하자면, 이건 잘못된 생각이기도 하고, 맞는 생각이기도 하다.
1. BFS,DFS는 완전탐색 중에 한 방법이다.
2. 세상의 모든 관계는 그래프로 나타낼 수 있다. (인간관계는 모르겠다)
길찾기 문제가 나오고, 2차원 맵이 나온다면, 2차원 맵의 각각 칸 = Node , 칸들 끼리의 연결관계 = Edge라고 생각하면 된다. 즉, 위의 예시에서는 (0,0) -> (1,0) -> (2,0)-> (3,0) -> (3,1)-> (3,2) -> (2,3)-> (1,3)-> (1,4) 로 진행이 되고있다. 이렇게 나타내니까 , 마치 노드끼리, edge로 연결되어있는 그래프와 똑같이 느껴진다.
BFS,DFS로 탐색하는 방법
1. 방문했던 곳은 방문하지 않음.
- chk를 boolean으로 선언해도 되고, 정수형으로 선언해서, 기록해줘도된다. boolean선언이냐, 정수형 선언이냐에 따라서, 장/단점은 있으나, 뭘로 해줘도 상관없음!
2. 범위체크는 항상 먼저 !
- 탐색을 할때, 범위를 먼저 벗어나게 되면, out of index가 발생하므로, 항상 탐색하기 전에는 범위체크가 우선적으로 진행되어야한다.
3. 상대좌표의 개념을 써서, if문의 작성을 줄이자!
- 상,하,좌,우를 탐색 또는 , 상,하,좌,우,대각선들 (팔방)으로 탐색해야하는 경우가 있는데, 이때 상대좌표의 개념을 사용해주면 좋다.
코드로 구현해보자. (BFS)
dy = (0, 1, 0, -1)
dx = (1, 0, -1, 0)
#상대좌표 , 나는 오른쪽 -> 위쪽 -> 왼쪽 -> 아래쪽 순으로 탐색하는걸 좋아함.
def is_valid_coord(y, x):
return 0 <= y < 100 and 0 <= x < 100
def bfs(sy, sx): # start y, x
chk = [[False] * 100 for _ in range(100)]
chk[sy][sx] = True
q = deque()
q.append((sy, sx))
while q:
y, x = q.popleft()
for k in range(4):
ny = y + dy[k] # next y, x
nx = x + dx[k]
if is_valid_coord(ny, nx) and not chk[ny][nx]:
chk[ny][nx] = True
q.append((ny, nx))
코드로 구현(DFS)
dy = (0, 1, 0, -1)
dx = (1, 0, -1, 0)
chk = [[False] * 100 for _ in range(100)]
def is_valid_coord(y, x):
return 0 <= y < 100 and 0 <= x < 100
def dfs(y, x):
for k in range(4):
ny = y + dy[k] # next y, x
nx = x + dx[k]
if is_valid_coord(ny, nx) and not chk[ny][nx]:
chk[ny][nx] = True
dfs(ny, nx)
chk[sy][sx] = True # start y, x
dfs(sy, sx)
'알고리즘 개념(Concept)' 카테고리의 다른 글
[알고리즘,개념] DP(Dynamic Programming) (0) | 2022.01.07 |
---|---|
[알고리즘,개념] Backtracking (0) | 2022.01.05 |
[개념/파이썬/알고리즘] BFS(Breadth First Search) (0) | 2021.11.13 |
[개념/파이썬/알고리즘] DFS (Depth First Search) (0) | 2021.11.13 |
[개념,그래프] 인접행렬 ,인접리스트 - 그래프를 코드로 ! (0) | 2021.11.11 |