당신은 1~n 사이의 수가 적힌 카드가 하나씩 있는 카드 뭉치와 동전 coin개를 이용한 게임을 하려고 합니다. 카드 뭉치에서 카드를 뽑는 순서가 정해져 있으며, 게임은 다음과 같이 진행합니다.
예를 들어 n = 12, coin = 4이고 [3, 6, 7, 2, 1, 10, 5, 9, 8, 12, 11, 4] 순서대로 카드를 뽑도록 카드 뭉치가 섞여 있습니다.
처음에 3, 6, 7, 2 카드 4장(= n/3)과 동전 4개(= coin)를 가지고 시작합니다. 다음 라운드로 진행하기 위해 내야 할 카드 두 장에 적힌 수의 합은 13(= n+1)입니다. 다음과 같은 방법으로 최대 5라운드까지 도달할 수 있습니다.
처음에 가진 동전수를 나타내는 정수 coin과 카드를 뽑는 순서대로 카드에 적힌 수를 담은 1차원 정수 배열 cards가 매개변수로 주어질 때, 게임에서 도달 가능한 최대 라운드의 수를 return 하도록 solution 함수를 완성해 주세요.
coin | cards | result |
---|---|---|
4 | [3, 6, 7, 2, 1, 10, 5, 9, 8, 12, 11, 4] | 5 |
3 | [1, 2, 3, 4, 5, 8, 6, 7, 9, 10, 11, 12] | 2 |
2 | [5, 8, 1, 2, 9, 4, 12, 11, 3, 10, 6, 7] | 4 |
10 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] | 1 |
우선 첫번째 풀이는 BFS 로 모든 경우의 수를 다 확인 해 보려고 했다.
카드의 길이가 1,000 밖에 안돼서 가능할 거라고 생각했다.
하지만, 실제로 탐색 범위는 카드 길이 1,000 에 다음 라운드로 진행 할 수 있는 경우의 수 네가지로 아마 최악의 경우 1,000 ^ 4 번 탐색해야 해서 시간 초과가 발생하는 것 같다.
BFS 탐색 경우의 수는 아래와 같다.
탐색이 전부 끝났을 때 최대 라운드를 정답으로 출력한다.
예제와 테스트케이스 7번까지는 위 풀이로 정답을 맞을 수 있었다.
하지만 카드의 길이가 커지면서 시간초과로 코드가 터지고 말았다.
그럼 DP 로 풀어야 하나.. 생각을 하면서 다음 라운드로 넘어갈 수 있는 방법을 생각했다.
정답은 이거였다.
현재의 조합이 정답 조합이 아닐 수 있기 때문에, 과거에 뽑았던 카드들이 최선의 선택이 아닐 수도 있다.
그 말은 카드를 당장 뽑지 않고, 필요할 때만 뽑는 다는 것은 최적의 선택을 했을 때의 경우와 같다는 말이 된다.
카드를 뽑은 경우 사용하지 않더라도, 배열에 넣어 놓고 언제라도 필요 할 때 사용할 수 있게 유지 시킨다.
코인을 충분히 가지고 있다면 코인을 소모하여 다음 라운드로 넘어갈 수 있다.
다만, 카드덱이 더 이상 존재하지 않는 경우 그 라운드가 최종 라운드가 된다.
from collections import deque
def solution(coin, cards):
answer = 0
n = len(cards)
target = n + 1
deck = cards[:n // 3]
cards = deque(cards[n // 3:])
picked = []
while cards:
answer += 1
a, b = cards.popleft(), cards.popleft()
picked.append(a)
picked.append(b)
is_possible = False
for i in deck:
if target - i in deck:
deck.remove(i)
deck.remove(target - i)
is_possible = True
break
if is_possible:
continue
if coin >= 1:
for i in deck:
if target - i in picked:
deck.remove(i)
picked.remove(target - i)
is_possible = True
break
if is_possible:
coin -= 1
continue
if coin >= 2:
for i in picked:
if target - i in picked:
picked.remove(i)
picked.remove(target - i)
is_possible = True
break
if is_possible:
coin -= 2
continue
if not is_possible:
break
if is_possible:
answer += 1
print(answer)
return answer