[BOJ 12934] 턴 게임
- 문제풀이
문제
윤호와 동혁이는 BOJ 알고리즘 캠프에 참가중이다. 두 사람은 문제가 너무 안 풀릴 때는 게임을 하고 문제를 풀기도 한다.
게임은 턴으로 이루어져 있으며, 각 턴의 승자는 두 사람 중에 한 사람이다. i번째 턴을 승리한 사람은 점수 i점을 갖게 되고, 턴은 1부터 시작한다.
두 정수 x와 y가 주어졌을 때, 윤호의 점수가 x, 동혁이의 점수가 y가 되는 것이 가능한지 불가능한지 구하는 프로그램을 작성하시오. 만약, 가능하다면 윤호가 최소 몇 번 이겨야 하는지도 구하시오.
입력
첫째 줄에 두 정수 x와 y가 주어진다. (0 ≤ x, y ≤ 1012)
출력
윤호가 최소 몇 번 이겨야 하는지 출력한다. 불가능한 경우에는 -1을 출력한다.
제한
| 시간 제한 | 메모리 제한 |
|---|---|
| 2sec | 512MB |
힌트
윤호가 1, 2, 4 턴을 이기고, 동혁이가 3, 5, 6 턴을 이겼다면 가능한 결과이다. 윤호의 승리 횟수가 최소가 되는 경우는 윤호가 1, 6 턴을 이기고, 동혁이가 2, 3, 4, 5를 이긴 것이다.
풀이
게임의 각 $i$번째 턴에서 승리한 사람이 $i$점을 가져갈 때, 최종 점수가 각각 $x$와 $y$가 되는 것이 가능한지 확인하고, 가능하다면 윤호($x$)의 최소 승리 횟수를 구하는 문제다.
먼저 게임이 총 몇 턴($n$) 동안 진행되었는지 알아내야 한다. $i$번째 턴까지의 모든 점수의 합은 $1 + 2 + \dots + n = \frac{n(n+1)}{2}$이므로, 두 사람의 점수 합인 $x+y$는 반드시 어떤 $n$에 대한 삼각수여야 한다.
\[x + y = \frac{n(n+1)}{2}\]따라서 반복문을 통해 위 식을 만족하는 정수 $n$이 존재하는지 먼저 확인한다. 만약 점수의 총합이 삼각수가 아니라면 문제의 조건이 성립할 수 없으므로 $-1$을 출력한다.
조건이 성립한다면, 윤호가 $x$점을 얻기 위해 필요한 최소 승리 횟수를 구해야 한다. 승리 횟수를 최소화하기 위해서는 한 번 이길 때마다 최대한 큰 점수를 가져가는 것이 유리하다. 이는 그리디 알고리즘을 통해 해결할 수 있다.
마지막 턴인 $n$점부터 시작하여 아래와 같은 로직을 적용한다.
- 현재 남은 목표 점수 $x$가 현재 턴의 점수 $n$보다 크거나 같다면, 윤호가 해당 턴에서 승리하여 $n$점을 가져가고 $x$에서 $n$을 뺀다.
- 만약 $x$가 $n$보다 작다면, 윤호가 $x$점짜리 어느 한 턴에서 승리하여 정확히 $x$점을 채우고 종료한다.
이 과정에서 윤호가 승리한 횟수를 카운트하면 최솟값을 얻을 수 있다. 점수 $x, y$의 범위가 최대 $10^{12}$에 달하므로 모든 계산 과정에서 long long 자료형을 사용해야 오버플로우를 방지할 수 있다.
소스코드
Github Link : Source Code
참고 알고리즘 : 그리디 알고리즘