[프로그래머스] 양과 늑대 (2022 KAKAO BLIND RECRUITMENT) - Python
문제
아이디어
처음엔 BFS로 접근했는데 방문 처리 시점을 어떻게 해야할지 몰라서 방황했다.
결국 DFS로 풀 수 있었다.
먼저 그래프 탐색을 위해 주어진 간선 정보를 바탕으로 단방향 인접리스트를 만든다.
트리 형식으로 주어지기도 하고, 부모 -> 자식 순서로 방문하기 때문에 단방향 인접리스트면 충분하다.
(자식 -> 부모 방향의 탐색은 전혀 필요없다.)루트 노드인 0번을 시작으로 dfs 탐색을 한다.
재귀 탐색 과정에서 필요한 정보는누적 양, 누적 늑대, 방문 가능한 노드 리스트
이다.누적 양
: 최대값 갱신을 위해 필요
누적 늑대
: 늑대 수가 더 많은 순간 불필요한 탐색을 종료하기 위해 필요
방문 가능한 노드 리스트
: 거쳐온 노드들의 자식 노드들을 언제든 즉시 방문할 수 있기 때문에 모든 경우의 수 탐색을 위해 필요처음 루트 노드 0번부터 탐색을 시작한다.
주어진 예제 1번을 예로 들어보자.
0번 노드를 방문했을 때 다음으로 방문 가능한 노드들은 [1, 8]이 된다.
그 다음으로 1번 노드를 방문했을 때, 방문 가능한 노드 리스트는 1의 자식 노드 [2, 4]를 포함하여 [1, 8, 2, 4]가 될 것이다. 이 때 1번 노드는 이미 방문했던 노드이므로 리스트에 있어봤자 무의미하다.
(물론 리스트에서 값을 제거하여 전달해도 되지만 불필요한 연산 시간이 추가될 것 같아서) visited[1]을 체크하여 중복 방문할 일을 없도록 한 뒤 재귀 호출한다. 재귀 호출이 끝난 뒤에는 다시 방문 체크를 해제하여 다음 탐색에 지장이 없도록 해야한다.다음으로 8번 노드를 방문했을 때, 방문 가능한 노드 리스트는 8의 자식 노드 [7, 9]를 포함하여 [1, 8, 2, 4, 7, 9]가 될 것이다. 마찬가지로 8번 노드를 방문 체크하고 재귀 호출한다.
이와 같은 방식으로 방문 체크와 해제, 노드의 값(늑대인지 양인지)에 따라 양 개수, 늑대 개수 인자와 노드 리스트를 전달하며 dfs를 수행한다.
또한 매 탐색마다 최대값을 업데이트 한다.
(이 부분에서 착각할 수 있는게늑대>= 양
이 될 때만 값을 갱신하면 안된다. 늑대가 양보다 적을 때 모은 양이 가장 많다면, 거기까지만 양을 모으고 그만두면 되기 때문에 항상 최대값을 갱신해줘야 한다.)모든 노드들을 방문하면 탐색이 종료되고 answer에 최대값이 저장되어 있다.
전체 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def solution(info, edges):
global answer
answer = 0
adj = [[] for _ in range(len(info))]
visited = [0] * len(info)
for p, c in edges:
adj[p].append(c)
def dfs(sheep, wolf, nxt):
global answer
if wolf >= sheep:
return
if sheep > answer:
answer = sheep
for i in nxt:
if not visited[i]:
visited[i] = 1
s, w = (sheep, wolf+1) if info[i] else (sheep+1, wolf)
dfs(s, w, nxt+adj[i])
visited[i] = 0
dfs(1, 0, adj[0])
return answer