给定一个整数 N和两个玩家,A 和 B 正在玩游戏。在每个玩家的回合中,该玩家通过从当前 N 中减去当前 N (小于 N)的除数来进行移动,从而为下一回合形成一个新的 N。没有任何除数可以减去的玩家输掉游戏。任务是判断如果玩家 A 进行第一轮,哪个玩家赢得游戏,假设两个玩家都玩得最佳。
例子:
Input : N = 2
Output : Player A wins
Explanation :
Player A chooses 1, and B has no more moves.
Input : N = 3
Output : Player B wins
Explanation :
Player A chooses 1, player B chooses 1, and A has no more moves.
方法 :
上面提到的这个问题可以使用动态规划来解决。
- 我们将采用具有 2 个状态的 DP,即
N -> current number left
A -> boolean value to decide if it’s player A’s turn or not
- 在每个状态,我们将尝试找到 N 的所有除数,并尝试找到当前玩家获胜的下一个状态。对于玩家 A,我们将尝试找到返回值为 true 的下一个状态,而对于玩家 B,我们将尝试找到返回值为 false 的下一个状态(因为 false 代表玩家 A 的失败)。
- 基本情况是 N=1,玩家 A 总是输,N=2,玩家 B 总是输。
- 要找到答案,我们只需要找到 DP[ N ][ 1 ] 的值。
下面是上述方法的实现:
C++
// C++ program for implementation of
// Optimal Strategy for the Divisor
// Game using Dynamic Programming
#include
using namespace std;
// Recursive function to find the winner
bool divisorGame(int N, bool A, int dp[][2])
{
// check if N=1 or N=3 then player B wins
if (N == 1 or N == 3)
return false;
// check if N=2 then player A wins
if (N == 2)
return true;
// check if current state already visited
// then return the previously obtained ans
if (dp[N][A] != -1)
return dp[N][A];
// check if currently it is player A's turn
// then initialise the ans to 0
int ans = (A == 1) ? 0 : 1;
// Traversing across all the divisors of N
// which are less than N
for (int i = 1; i * i <= N; i++) {
// check if current value of
// i is a divisor of N
if (N % i == 0) {
// check if it is player A's turn
// then we need at least one true
if (A)
ans |= divisorGame(N - i, 0, dp);
// Else if it is player B's turn
// then we need at least one false
else
ans &= divisorGame(N - i, 1, dp);
}
}
// Return the current ans
return dp[N][A] = ans;
}
// Driver code
int main()
{
// initialise N
int N = 3;
int dp[N + 1][2];
memset(dp, -1, sizeof(dp));
if (divisorGame(N, 1, dp) == true)
cout << "Player A wins";
else
cout << "Player B wins";
return 0;
}
Java
// Java program for implementation of
// optimal strategy for the divisor
// game using dynamic programming
import java.util.*;
class GFG {
// Recursive function to find the winner
static int divisorGame(int N, int A, int dp[][]) {
// Check if N = 1 or N = 3 then player B wins
if (N == 1 || N == 3)
return 0;
// Check if N = 2 then player A wins
if (N == 2)
return 1;
// Check if current state already visited
// then return the previously obtained ans
if (dp[N][A] != -1)
return dp[N][A];
// Check if currently it is player A's turn
// then initialise the ans to 0
int ans = (A == 1) ? 0 : 1;
// Traversing across all the divisors of N
// which are less than N
for (int i = 1; i * i <= N; i++) {
// Check if current value of
// i is a divisor of N
if (N % i == 0) {
// Check if it is player A's turn
// then we need at least one true
if (A == 1)
ans |= divisorGame(N - i, 0, dp);
// Else if it is player B's turn
// then we need at least one false
else
ans &= divisorGame(N - i, 1, dp);
}
}
// Return the current ans
return dp[N][A] = ans;
}
// Driver code
public static void main(String[] args) {
// Initialise N
int N = 3;
int[][] dp = new int[N + 1][2];
for (int i = 0; i < N + 1; i++) {
for (int j = 0; j < 2; j++) {
dp[i][j] = -1;
}
}
if (divisorGame(N, 1, dp) == 1)
System.out.print("Player A wins");
else
System.out.print("Player B wins");
}
}
// This code contributed by sapnasingh4991
Python3
# Python3 program for implementation of
# Optimal Strategy for the Divisor
# Game using Dynamic Programming
from math import sqrt
# Recursive function to find the winner
def divisorGame(N,A,dp):
# check if N=1 or N=3 then player B wins
if (N == 1 or N == 3):
return False
# check if N=2 then player A wins
if (N == 2):
return True
# check if current state already visited
# then return the previously obtained ans
if (dp[N][A] != -1):
return dp[N][A]
# check if currently it is player A's turn
# then initialise the ans to 0
if(A == 1):
ans = 0
else:
ans = 1
# Traversing across all the divisors of N
# which are less than N
for i in range(1,int(sqrt(N))+1,1):
# check if current value of
# i is a divisor of N
if (N % i == 0):
# check if it is player A's turn
# then we need at least one true
if (A):
ans |= divisorGame(N - i, 0, dp)
# Else if it is player B's turn
# then we need at least one false
else:
ans &= divisorGame(N - i, 1, dp)
dp[N][A] = ans
# Return the current ans
return dp[N][A]
# Driver code
if __name__ == '__main__':
# initialise N
N = 3
dp = [[-1 for i in range(2)] for j in range(N+1)]
if (divisorGame(N, 1, dp) == True):
print("Player A wins")
else:
print("Player B wins")
# This code is contributed by Surendra_Gangwar
C#
// C# program for implementation of
// optimal strategy for the divisor
// game using dynamic programming
using System;
class GFG {
// Recursive function to find the winner
static int divisorGame(int N, int A,
int [,]dp)
{
// Check if N = 1 or N = 3
// then player B wins
if (N == 1 || N == 3)
return 0;
// Check if N = 2 then player A wins
if (N == 2)
return 1;
// Check if current state already visited
// then return the previously obtained ans
if (dp[N, A] != -1)
return dp[N, A];
// Check if currently it is player A's turn
// then initialise the ans to 0
int ans = (A == 1) ? 0 : 1;
// Traversing across all the divisors of N
// which are less than N
for(int i = 1; i * i <= N; i++)
{
// Check if current value of
// i is a divisor of N
if (N % i == 0)
{
// Check if it is player A's turn
// then we need at least one true
if (A == 1)
ans |= divisorGame(N - i, 0, dp);
// Else if it is player B's turn
// then we need at least one false
else
ans &= divisorGame(N - i, 1, dp);
}
}
// Return the current ans
return dp[N, A] = ans;
}
// Driver code
public static void Main(String[] args)
{
// Initialise N
int N = 3;
int[,] dp = new int[N + 1, 2];
for(int i = 0; i < N + 1; i++)
{
for(int j = 0; j < 2; j++)
{
dp[i, j] = -1;
}
}
if (divisorGame(N, 1, dp) == 1)
{
Console.Write("Player A wins");
}
else
{
Console.Write("Player B wins");
}
}
}
// This code is contributed by amal kumar choubey
Javascript
输出:
Player B wins
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live