알고리즘/PROGRAMMERS (Python)

[ 프로그래머스 / Lv2 ] 광물 캐기 ( 파이썬 Python )

Heeto 2023. 3. 30. 13:15
링크 : https://school.programmers.co.kr/learn/courses/30/lessons/172927
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

코드


def solution(picks, minerals):
    
    graph =[[1,1,1],
            [5,1,1],
            [25,5,1]] 
    
    def mineralNum(s):
        if s == "diamond":
            return 0
        if s == "iron":
            return 1
        if s == "stone":
            return 2
        
    def DFS(cnt,prePick,total):
        nonlocal answer,picks
        
        if cnt >= len(minerals):
            answer = min(answer,total)
            return
        
        mNum = mineralNum(minerals[cnt])
        
        if (cnt+1) % 5 == 0:
            if picks.count(0) == 3:
                answer = min(answer,total+graph[prePick][mNum])
                return
            for pick in range(len(picks)):
                if picks[pick] > 0:
                    picks[pick] -= 1
                    DFS(cnt+1, pick, total+graph[prePick][mNum])
                    picks[pick] += 1
            return
        else:
            DFS(cnt+1, prePick, total+graph[prePick][mNum])
            
    answer = 1e9
    for pick in range(len(picks)):
        if picks[pick] > 0:
            picks[pick] -= 1
            DFS(0,pick,0)
            picks[pick] += 1
    
    return answer

 

풀이


문제내용이 마인크래프트에서 영감을 받은 문제인 것 같아서 재밌었던 문제이다.

 

한 곡괭이당 무조건 5개씩 캘 수 있으니 5개를 캘 때마다 곡괭이를 바꿔주어야 한다.

처음에는 이 곡괭이를 바꿔줄 때 효율성을 계산해서 다음 5개를 가장 적은 시간에 해결할 수 있는 곡괭이를 선택할까 했다.

하지만 이 효율성을 계산하는 과정이 너무 복잡하고 따져야 할 조건이 많았다. 그래서 이 문제는 무조건 완전탐색이라고 생각했다.

 

5번째 광물, 즉 곡괭이를 바꿔줘야 할 타이밍이 올 때마다 DFS로 가지를 뻗어나간다.

각각의 가지들은 하나의 곡괭이를 선택하여 3방향씩 뻗어나가므로 시간복잡도는 3^10이 최대가 되어서 시간초과가 나지는 않을 것이라 생각했다.

모든 광물을 캐거나 곡괭이가 모두 사용되면 정답을 갱신하고 그렇지 않다면 계속해서 가지를 뻗어나간다.

가지를 뻗어나갈 때 picks[pick] -= 1 은 사용한 곡괭이의 개수를 줄이는 과정인데 DFS를 수행한 이후에는 다른 가지에 영향이 가지 않도록 다시 되돌려주어야 한다는 것을 잊으면 안된다.