PS/백준

[BOJ] 백준 11062번 : 카드 게임 (JAVA)

제이온 (Jayon) 2020. 8. 27.

문제

근우와 명우는 재미있는 카드 게임을 하고 있다. N개의 카드가 일렬로 놓여 있다. 각 카드에는 점수가 적혀있다. 근우부터 시작하여 번갈아가면서 턴이 진행되는데 한 턴에는 가장 왼쪽에 있는 카드나 가장 오른쪽에 있는 카드를 가져갈 수 있다. 카드가 더 이상 남아있지 않을 때까지 턴은 반복된다. 게임의 점수는 자신이 가져간 카드에 적힌 수의 합이다.

 

근우와 명우는 서로 자신의 점수를 가장 높이기 위해 최선의 전략으로 게임에 임한다. 놓여있는 카드의 개수 N과 카드가 놓여있는 상태가 주어졌을 때 근우가 얻는 점수를 구하는 프로그램을 작성하시오.

 

예를 들어 카드가 [4, 3, 1, 2]로 놓여있다고 하자. 근우는 처음에 4가 적힌 카드를 가져가고, 명우는 3이 적힌 카드를 가져간다. 그리고 근우는 2가 적힌 카드를 가져가고, 명우는 마지막으로 1이 적힌 카드를 가져간다. 이때 근우와 명우는 최선의 전략으로 임했으며, 근우가 얻는 점수는 6이다.

 

 

입력

입력의 첫 줄에는 테스트케이스의 수 T가 주어진다.

 

각 테스트케이스 마다 첫 줄에는 카드의 개수 N(1 ≤ N ≤ 1,000)이 주어진다. 두 번째 줄에는 N개의 자연수가 공백으로 구분되어 주어지는데, i번째로 주어지는 수는 왼쪽에서 i번째에 놓인 카드에 적힌 수를 의미한다. 카드에 적혀있는 수는 1이상 10,000이하다.

 

 

출력

각 테스트케이스마다 근우와 명우가 최선의 전략으로 임할 때 근우가 얻게되는 점수를 줄로 구분하여 출력한다.

 

 

풀이

다이나믹 프로그래밍을 통해 해결할 수 있는 문제였습니다.

 

근우와 명우는 항상 최선의 전략으로 카드를 뽑는다고 하였습니다.

이 말을 풀어서 설명하자면, 근우는 왼쪽 카드와 오른쪽 카드 중 더 점수가 높은 카드를 뽑아야 하고, 명우는 근우가 왼쪽 카드와 오른쪽 카드 중 더 낮은 점수를 갖도록 만드는 카드를 뽑아야 합니다.

 

따라서, 가능한 모든 경우를 탐색하되, 이미 특정 카드를 뽑았을 때 점수가 몇 점인지 알 수 있는 경우를 메모이제이션을 통해 저장해 두는 방식을 사용하면 됩니다.

 

 

dp[서로의 차례][남은 카드 중 맨 왼쪽][남은 카드 중 맨 오른쪽]

 

 

으로 배열을 정의한 후, 차례가 0일 때는 근우, 차례가 1일 때는 명우로 설정하여 위에서 언급한 최선의 전략을 재귀 함수로 짜시면 됩니다.

 

여기서 기저 사례는 카드의 맨 왼쪽 위치가 맨 오른쪽 위치보다 크거나 같을 때인데, 근우 차례일 경우 해당 카드의 점수를 더하고, 명우 차례일 경우 더하지 않아야 합니다.

 

 

아래는 위 내용을 정리한 소스코드입니다.

 

 

소스코드

 

지적 혹은 조언 환영합니다! 언제든지 댓글로 남겨주세요.

댓글

추천 글