정해진 횟수만큼 숫자판을 교환했을 때, 가장 큰 상금 값을 구하는 문제.
def DFS(count):
global result # 현재까지 발견된 최대 숫자
if(count == 0): # 교환 횟수 달성 시 max 비교
_max = int(''.join(keypad))
result = max(_max, result) # 값 비교
return
for now in range(len(keypad)-1): # 현재 번호판
for max_idx in range(now+1, len(keypad)): # 다음 번호판 돌면서 확인
keypad[now], keypad[max_idx] = keypad[max_idx], keypad[now] # 번호판 교환
cur = ''.join(keypad)
if not (cur, count) in visited:
visited.append((cur, count))
DFS(count-1) # 교환횟수 차감해서 다시 호출
keypad[now], keypad[max_idx] = keypad[max_idx], keypad[now] # 백트래킹
T = int(input()) # 테스트 케이스의 수 T
for test_case in range(1, T+1):
keypad, cnt = input().split() # 숫자판의 정보, 교환 횟수
keypad = list(keypad) # list()로 문자열 쪼개기
result = 0
visited=[]
DFS(int(cnt))
print("#%d %s" %(test_case, result))
[문제풀이]
솔직히 이 문제는 못풀어서 포인트로 다른 분 코드를 참고했다.
for문을 사용한 Greedy 방식으로는 풀기가 어려운 문제다.
이 방식은 우선 가장 큰 숫자를 땡겨와야 하는데, 이로서 끝나는 문제가 아니다.
32881 -> 82831 (SWAP 1회시 최적O) -> 88231 (SWAP 2회시 최적X)
32881 -> 82381 (SWAP 1회시 최적X) -> 88321 (SWAP 2회시 최적O)
예를 들면 위처럼 32881이란 숫자일 경우 가장 큰 숫자 8을 앞으로 땡겨오는 첫 swap 시는 최대 상금이지만 그 다음 swap 시에는 아니게 된다. 그래서 무식하게 조건을 왕창 추가해 가며 풀어야 하는데 그래도 테스트 케이스 모두 통과하기가 무척 어렵다.
그러니 DFS+백트래킹을 활용한 완전탐색이 필요하다.
처음부터 어떤 숫자들끼리 바꿀지 선택하지 말고, 모든 숫자들을 다 바꿔가며 풀어야 하는데 완전 탐색으로 모든 교환을 시도할 시 시간 초과가 발생한다.
if not (cur, count) in visited:
visited.append((cur, count))
그래서 메모이제이션을 활용,
visited란 배열에 이미 방문했던 숫자와 교환 횟수를 기록해두고 같은 수가 나올 시 더 이상 탐색을 진행하지 않았다.
'코딩테스트 > SWEA' 카테고리의 다른 글
| [Python, 파이썬] SWEA 1208. [S/W 문제해결 기본] 1일차 - Flatten (0) | 2024.10.15 |
|---|---|
| [Python, 파이썬] SWEA 1954. 달팽이 숫자 (1) | 2024.10.15 |
| [Python, 파이썬] SWEA 1204. [S/W 문제해결 기본] 1일차 - 최빈수 구하기 (1) | 2024.10.15 |
| [Python, 파이썬] SWEA 1206. [S/W 문제해결 기본] 1일차 - View (0) | 2024.10.15 |
| [Python, 파이썬] SWEA 1859. 백만 장자 프로젝트 (1) | 2024.10.15 |