[프로그래머스] 피로도 / 완전탐색 / python
문제
https://school.programmers.co.kr/learn/courses/30/lessons/87946
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던전 탐험을 마쳤을 때 소모되는 "소모 피로도"가 있습니다. "최소 필요 피로도"는 해당 던전을 탐험하기 위해 가지고 있어야 하는 최소한의 피로도를 나타내며, "소모 피로도"는 던전을 탐험한 후 소모되는 피로도를 나타냅니다. 예를 들어 "최소 필요 피로도"가 80, "소모 피로도"가 20인 던전을 탐험하기 위해서는 유저의 현재 남은 피로도는 80 이상 이어야 하며, 던전을 탐험한 후에는 피로도 20이 소모됩니다.
이 게임에는 하루에 한 번씩 탐험할 수 있는 던전이 여러개 있는데, 한 유저가 오늘 이 던전들을 최대한 많이 탐험하려 합니다. 유저의 현재 피로도 k와 각 던전별 "최소 필요 피로도", "소모 피로도"가 담긴 2차원 배열 dungeons 가 매개변수로 주어질 때, 유저가 탐험할수 있는 최대 던전 수를 return 하도록 solution 함수를 완성해주세요.
제한사항
- k는 1 이상 5,000 이하인 자연수입니다.
- dungeons의 세로(행) 길이(즉, 던전의 개수)는 1 이상 8 이하입니다.
- dungeons의 가로(열) 길이는 2 입니다.
- dungeons의 각 행은 각 던전의 ["최소 필요 피로도", "소모 피로도"] 입니다.
- "최소 필요 피로도"는 항상 "소모 피로도"보다 크거나 같습니다.
- "최소 필요 피로도"와 "소모 피로도"는 1 이상 1,000 이하인 자연수입니다.
- 서로 다른 던전의 ["최소 필요 피로도", "소모 피로도"]가 서로 같을 수 있습니다.
풀이
아이디어
k값이 8까지 이기 때문에 생각보다 경우의 수가 많지는 않다
문제의 예시를 읽다보니 백트래킹이 생각났다
1→2→3 방문이 안되니 다시 1로 돌아가서 1→3→2방문을 선택한 것
그렇다면 DFS를 이용한 백트래킹으로 문제를 풀 수 있겠다
💥 tip
전체 경우의 수 중 조건을 만족하는 경우를 살펴보는 문제의 경우 백트래킹
- DFS, 순열 등으로 모든 경우의 수 탐색
- 조건문을 걸어 답이 될 수 없는 상황 정의
- 그런 상황에 탐색을 중지시킨 후 이전으로 돌아가 다른 경우의 수를 탐색
다른 풀이
모든 경우의 수를 본다는 차원에서의 다른 풀이는 순열이다
다른 사람의 풀이를 참고했다
순열을 이용해 모든 경우의 수를 찾은 다음, 조건에 불일치 하는 경우 넘어가는 식으로 구현 하면 됨
코드
DFS 풀이
def solution(k, dungeons):
global visited, answer
answer = 0
visited = [False for _ in range(len(dungeons))]
dfs(k, 0, dungeons)
return answer
def dfs(k, cnt, dungeons):
global answer
# 최대 값으로 변경
if cnt > answer:
answer = cnt
for i in range(len(dungeons)):
# 방문 하지 않고, 필요피로도보다 k가 큰거나 같은 경우
if not visited[i] and k >= dungeons[i][0]:
visited[i] = True
dfs(k-dungeons[i][1], cnt+1, dungeons)
visited[i] = False
순열 풀이
from itertools import permutations
def solution(k, dungeons):
answer = 0
# 순열을 이용해 모든 가능한 경우의 수를 구함
for i in permutations(dungeons, len(dungeons)):
temp = k
cnt = 0
for essential, reduce in i:
if temp >= essential:
temp -= reduce
cnt += 1
answer = max(cnt, answer)
return answer