1 분 소요

swea 1244 [S/W 문제해결 응용] 2일차 - 최대 상금

사용언어 : PYTHON

풀이

구현을 위한 생각


백트래킹을 사용하여 모든 경우를 중복없이 탐색한다.

모든 경우를 탐색하며 goal(주어진 숫자를 내림차순으로 정렬한 값)과 차이가 가장 작은 값이 정답이다.

💡 goal : 이동횟수 제한이 없다고 할 때, 숫자를 swap해서 도달할 수 있는 최대값은 내림차순으로 정렬한 값이다.

백트래킹


image

숫자카드 1,2,3,4가 있다고 할 때 두 번 교환할 수 있는 모든 경우는 위 그림과 같다.
(x표시는 중복되는 경우)

바로 직전에 교환한 경우보다 뒤의 경우만 조회하면 중복없이 교환할 수 있다.

바로 직전에 교환한 경우를 기억하기 위해서 stack을 활용하였다.

코드


def backTracking(m):
    global answer

    if m==n: # n번 교환한 경우 도달할 base case
        result=goal-int(''.join(l)) # goal값과 숫자를 교환한 값의 차이를 구함
        
        if result < answer: # 최솟값을 갱신
            answer=result
    
        return
    

    for i in range(0,len(l)-1):
        for j in range(i+1,len(l)):
            a,b=chk[-1] # 바로 직전에 교환한 카드 a,b
            if (i>=a and j>=b) or i>a: # 직전 경우를 활용하여 중복 제거 
                
                l[i],l[j]=l[j],l[i] # 교환
                chk.append([i,j]) # stack에 교환한 카드 push
                
                backTracking(m+1) # recursion으로 백트레킹하여 모든 경우를 탐색한다
                
                l[i],l[j]=l[j],l[i] # 탐색이 끝나면 교환했던 카드를 원상복구
                chk.pop() # stack 원상복구
                
                if answer==0: # 만약 answer이 0이라면 정답을 찾은 경우이므로 더이상 backtracking을 할 필요가 없다
                    return
    
T=int(input())



for i in range(T):
    
    l,n=map(int,input().split())
    l=list(str(l))
    goal=int(''.join(sorted(l,reverse=True)))
    answer=999999 # 6자리 중 가장 큰 값 999999(문제에서 최대 자릿수는 6으로 주어짐)
    chk=[[-1,-1]] # 바로 직전의 교환한 카드들을 기억하기위한 stack

    backTracking(0)

    print('#{} {}'.format((i+1),goal-answer))


댓글남기기