先决条件:
斯普拉格·格兰西定理
肮脏的数字
Nim是著名的游戏,其中两个玩家轮流从不同的堆中移除物品。在每个回合中,玩家必须从单个非空堆中移除一个或多个物品。游戏的获胜者是从最后一个非空堆中删除最后一个项目的任何玩家。
现在,对于每个非空堆,任一玩家都可以从该堆中删除零个物品,并将其计为他们的移动;但是,任何一位玩家每堆只能进行一次此移动。
给定每堆物品的数量,确定谁将赢得比赛;玩家1或玩家2。如果玩家1开始游戏,并且双方都处于最佳状态。
例子:
Input : 3 [18, 47, 34]
Output : Player 2 wins
G = g(18)^g(47)^g(34) = (17)^(48)^(33) = 0
Grundy number(G), for this game is zero.
Player 2 wins.
Input : 3 [32, 49, 58]
Output : Player 1 wins
G = g(31)^g(50)^g(57) = (17)^(48)^(33) = 20
Grundy number(G), for this game is non-zero.
Player 1 wins.
方法:
每堆的脏数是根据石头的数量计算的。为了补偿零移动,我们将不得不修改标准nim游戏中使用的脏度值。
如果堆大小是奇数;脏号码是size + 1,
如果堆的大小是均匀的;脏号码是size-1。
我们对所有的脏钱值进行XOR运算,以检查游戏的最终Grundy数(G)是否为非零或不决定谁是游戏的获胜者。
解释:
状态的脏数是一次有效移动所不能达到的最小正整数。
因此,我们需要从下往上计算每个n的mex值,以便我们可以得出每个n的粗略数。其中n是堆的大小。
获胜状态:无论对手做什么,当前玩家从中赢得比赛的价值元组。 (如果G!= 0)
输球状态:无论对手做什么,当前玩家将从其中输掉游戏的值的元组。 (如果G = 0)
For a given pile size n, we have two states:
(1) n with no zero moves available,
grundy number will same as standard nim game.
(2) n with zero moves available, we can
reach above state and other states with
zero moves remaining.
For, n = 0, g(0) = 0, empty pile
For, n = 1, we can reach two states:
(1) n = 0 (zero move not used)
(2) n = 1 (zero move used)
Therefore, g(1) = mex{0, 1} which implies
that g(1)=2.
For, n = 2, we can reach :
(1) n = 0 (zero move not used) state
because this is a valid move.
(2) n = 1 (zero move not used) is a valid
move, whose grundy nuber is 2.
Therefore, g(2) = mex{0,2} which implies
that g(2)=1.
note that n=1 (zero move used) is not a valid
move.
If we try to build a solution bottom-up
like this, it turns out that if n is even,
the grundy number is n - 1 and when it is odd,
the grundy is n + 1.
下面是上述方法的实现:
C++
// CPP program for the variation
// in nim game
#include
using namespace std;
// Function to return final
// grundy Number(G) of game
int solve(int p[], int n)
{
int G = 0;
for (int i = 0; i < n; i++) {
// if pile size is odd
if (p[i] & 1)
// We XOR pile size+1
G ^= (p[i] + 1);
else // if pile size is even
// We XOR pile size-1
G ^= (p[i] - 1);
}
return G;
}
// driver program
int main()
{
// Game with 3 piles
int n = 3;
// pile with different sizes
int p[3] = { 32, 49, 58 };
// Function to return result of game
int res = solve(p, n);
if (res == 0) // if G is zero
cout << "Player 2 wins";
else // if G is non zero
cout << "Player 1 wins";
return 0;
}
Java
// Java program for the variation
// in nim game
class GFG {
// Function to return final
// grundy Number(G) of game
static int solve(int p[], int n)
{
int G = 0;
for (int i = 0; i < n; i++) {
// if pile size is odd
if (p[i]%2!=0)
// We XOR pile size+1
G ^= (p[i] + 1);
else // if pile size is even
// We XOR pile size-1
G ^= (p[i] - 1);
}
return G;
}
//Driver code
public static void main (String[] args)
{
// Game with 3 piles
int n = 3;
// pile with different sizes
int p[] = { 32, 49, 58 };
// Function to return result of game
int res = solve(p, n);
if (res == 0) // if G is zero
System.out.print("Player 2 wins");
else // if G is non zero
System.out.print("Player 1 wins");
}
}
// This code is contributed by Anant Agarwal.
Python3
# Python3 program for the
# variation in nim game
# Function to return final
# grundy Number(G) of game
def solve(p, n):
G = 0
for i in range(n):
# if pile size is odd
if (p[i] % 2 != 0):
# We XOR pile size+1
G ^= (p[i] + 1)
# if pile size is even
else:
# We XOR pile size-1
G ^= (p[i] - 1)
return G
# Driver code
# Game with 3 piles
n = 3
# pile with different sizes
p = [32, 49, 58]
# Function to return result of game
res = solve(p, n)
if (res == 0): # if G is zero
print("Player 2 wins")
else: # if G is non zero
print("Player 1 wins")
# This code is contributed by Anant Agarwal.
C#
// C# program for the variation
// in nim game
using System;
class GFG {
// Function to return final
// grundy Number(G) of game
static int solve(int[] p, int n)
{
int G = 0;
for (int i = 0; i < n; i++) {
// if pile size is odd
if (p[i] % 2 != 0)
// We XOR pile size+1
G ^= (p[i] + 1);
else // if pile size is even
// We XOR pile size-1
G ^= (p[i] - 1);
}
return G;
}
// Driver code
public static void Main()
{
// Game with 3 piles
int n = 3;
// pile with different sizes
int[] p = { 32, 49, 58 };
// Function to return result of game
int res = solve(p, n);
if (res == 0) // if G is zero
Console.WriteLine("Player 2 wins");
else // if G is non zero
Console.WriteLine("Player 1 wins");
}
}
// This code is contributed by vt_m.
PHP
Javascript
输出:
Player 1 wins
时间复杂度: O(n)
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。