문제 설명
XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던전 탐험을 마쳤을 때 소모되는 "소모 피로도"가 있습니다. "최소 필요 피로도"는 해당 던전을 탐험하기 위해 가지고 있어야 하는 최소한의 피로도를 나타내며, "소모 피로도"는 던전을 탐험한 후 소모되는 피로도를 나타냅니다. 예를 들어 "최소 필요 피로도"가 80, "소모 피로도"가 20인 던전을 탐험하기 위해서는 유저의 현재 남은 피로도는 80 이상 이어야 하며, 던전을 탐험한 후에는 피로도 20이 소모됩니다. 이 게임에는 하루에 한 번씩 탐험할 수 있는 던전이 여러개 있는데, 한 유저가 오늘 이 던전들을 최대한 많이 탐험하려 합니다. 유저의 현재 피로도 k와 각 던전별 "최소 필요 피로도", "소모 피로도"가 담긴 2차원 배열 dungeons 가 매개변수로 주어질 때, 유저가 탐험할수 있는 최대 던전 수를 return 하도록 solution 함수를 완성해주세요.
k는 1 이상 5,000 이하인 자연수입니다. dungeons의 세로(행) 길이(즉, 던전의 개수)는 1 이상 8 이하입니다. dungeons의 가로(열) 길이는 2 입니다. dungeons의 각 행은 각 던전의 ["최소 필요 피로도", "소모 피로도"] 입니다. "최소 필요 피로도"는 항상 "소모 피로도"보다 크거나 같습니다. "최소 필요 피로도"와 "소모 피로도"는 1 이상 1,000 이하인 자연수입니다. 서로 다른 던전의 ["최소 필요 피로도", "소모 피로도"]가 서로 같을 수 있습니다.
풀이
던전이 8개라면, 던전을 탐색하는 경우의 수는 8! 이다. 8중 for 구문을 만들거나, 순열에 관련된 함수를 사용해야한다.
전체 탐색을 하는 것이 내가 생각할 수 있는 최선의 방법인 것 같다.
from itertools import permutations # 순열 함수를 이용한다.
def goin(k, arr): # 피로도와 2차원 배열인 던전 순서를 받는다.
cnt = 0
for i in arr:
if k>=i[0]: # 피로도가 허용치이면 연산을 한다.
k-=i[1]
cnt+=1
return cnt # 방문한 던전을 센다
def solution(k, dungeons):
arr = list(permutations(dungeons)) # 순열로 찾아낸 모든 배열을 구한다
cnt = []
for i in arr:
cnt.append(goin(k, i))
return max(arr1) # 방문한 던전의 초댓값을 찾는다.
전체 탐색 말고 다른 방법을 찾아보려고 이틀을 고민했는데, 막상 최후의 방법이라는 생각으로 전체 탐색을 시도하니 5분도 안되어 코드를 짜고 통과해버렸다.
평소에 연습할 때, 수학적으로 간단하게 표현할 수 있는 상황을 기억해두고 그 외의 상황에는 전체 탐색을 과감히 시도해야할 것 같다.
재귀 함수로 푼 다른 사람의 풀이를 보자. 이 풀이는 깊이 우선 탐색(DFS)로 접근했다.
answer = 0
def dfs(k, cnt, dungeons):
global answer
if cnt > answer:
answer = cnt
for j in range(N):
if k >= dungeons[j][0] and not visited[j]: # j는 0,1,2가 반복하지만, 재귀함수로 여러 층 반복
visited[j] = 1
dfs(k - dungeons[j][1], cnt + 1, dungeons) # 재귀
visited[j] = 0
def solution(k, dungeons):
global N, visited
N = len(dungeons) # 던전 개수만큼 반복한다.
visited = [0] * N # 들리지 않은 던전은 0으로 표현
dfs(k, 0, dungeons) # 재귀
return answer
dungeons[ j ] 의 j가 0,1,2 를 반복할 때, 재귀 함수에서도 j 는 0,1,2를 반복하며, 실제로는 던전이 3개( N=3 )이므로 3층 구조이다.
하지만, 재귀함수가 어떻게 실행되고 어떻게 빠져나오는지 시각화가 잘 되지 않았다. Python Tutor를 참고하여 재귀함수 구동 순서를 익혔다.
↓ Python Tutor 를 이용해서 메모리가 할당되고 캐쉬가 생기고 사라지는 것을 시각화하여 볼 수 있다.
https://pythontutor.com/visualize.html#mode=edit
Python Tutor code visualizer: Visualize code in Python, JavaScript, C, C++, and Java
Please wait ... your code is running (up to 10 seconds) Write code in Python 3.11 [newest version, latest features not tested yet!] Python 3.6 [reliable stable version, select 3.11 for newest] C (C17 + GNU extensions, gcc 9.3) C++ (C++20 + GNU extensions,
pythontutor.com
출처
https://school.programmers.co.kr/learn/courses/30/lessons/87946
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
'Programing > 프로그래머스 오답노트' 카테고리의 다른 글
[프로그래머스] n진수 게임 (0) | 2023.09.30 |
---|---|
[프로그래머스] [3차]압축 - ( 문자열 슬라이싱으로 dict.keys 조사 ) (0) | 2023.09.29 |
[프로그래머스] 깊이/너비 우선 탐색 - ( 전부 조사하는 방법 ) (0) | 2023.09.29 |
[프로그래머스] [1차]뉴스 클러스터링 (1) | 2023.09.28 |
[프로그래머스] 튜플 - ( list에 list도 append 가능, 2차원 배열 ) (0) | 2023.09.28 |
댓글