알고리즘/코테
[프로그래머스 258707] n+1 카드게임
kiwiiiv
2025. 1. 11. 19:49
https://school.programmers.co.kr/learn/courses/30/lessons/258707
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
카드 게임을 진행할 수 있는 최대 라운드 수를 구해야 함
초기 접근 방식
매 라운드마다 다음과 같은 경우의 수가 존재하므로, dfs 알고리즘을 떠올림
: 카드 두 장 구매 / 카드 한 장 구매 / 구매하지 않음
하지만 dfs를 적용할 경우 카드 배열의 최대 길이는 1000이니까
대략 3^500 의 시간복잡도가 발생 > 시간초과
따라서 greedy 방식으로 바꾸어서 풀이(타 풀이를 참고했다..)
- 매 라운드마다 카드를 버리는 게 아닌, 따로 저장해 두기
- 코인 소모를 최소한으로(너무당연함)
문제에서의 입출력 예#3을 보면, 2라운드에서 12, 11 두 장의 카드를 가지면서, 해당 라운드에서는 카드 12 만(기존 카드 1과 함께) 소모. 3라운드에서 나머지 11 카드를 소모하여 플레이한다.
-> 이 때 11이라는 카드를 2라운드에서 갖고오든 3라운드에서 갖고오든 동일하게 취급되기 때문에, 해당 라운드를 플레이할 페어가 존재하다면 최대한 코인을 소모하지 않으면서 게임을 이어나가야 최적의 결과를 얻을 수 있다 - 그래서 greedy
import java.util.*;
class Solution {
public int solution(int coin, int[] cards) {
//init
int currPair = 0, currCoin = coin;
int goal = cards.length + 1;
HashSet<Integer> currCards = new HashSet<>();
HashSet<Integer> remain = new HashSet<>();
for(int i=0; i<cards.length/3; i++){
int curr = cards[i];
if(!currCards.contains(goal - curr)){
currCards.add(cards[i]);
}else {
currCards.remove(goal - curr);
currPair ++;
}
}
int round = 0;
for(int i=cards.length/3; round <= currPair && currCoin > 0 && i<cards.length; i+=2){
for(int j=0; j<2; j++){
if(currCoin >=1 && currCards.contains(goal - cards[i+j])) { //new - old matching
currCoin--;
currPair++;
currCards.remove(goal - cards[i + j]);
}else{
remain.add(cards[i+j]);
}
}
if(round >= currPair && currCoin >= 2){ //new - new matching
for(int card : remain){
if(remain.contains(goal - card)){
remain.remove(card);
remain.remove(goal-card);
currPair++;
currCoin-=2;
break;
}
}
}
round ++;
}
return currPair + 1;
}
}