游戏中你有N
堆石头,每个玩家轮到他必须从一堆中移除至少一块石头,并且移除最后一块石头的玩家输了。
我从基础案例
开始,在十几个案例中写出了胜利者/*
stones | winner | N | ones
========================================
{1} | Second | 1 | 1
{i}, i>1 | First | 1 | 0
{1,1} | First | 2 | 2
{1,i}, i>1 | First | 2 | 1
{i,j}, i,j>1 | Second | 2 | 0
{1,1,1} | Second | 3 | 3
{1,1,i}, i>1 | First | 3 | 2
{1,i,j}, i,j>1 | First | 3 | 1
{i,j,k}, i,j,k>1 | First | 3 | 0
{1,1,1,1} | First | 4 | 4
{1,1,1,i} | First | 4 | 3
{1,1,i,j}, i,j>1 | Second | 4 | 2
{1,i,j,k}, i,j,k>1 | First | 4 | 1
{i,j,k,m}, ... | Second | 4 | 0
*/
从那以后我想我推导了一个公式
static string GetWinner(int[] piles)
{
int n = piles.Length, m = piles.Count(stones => stones == 1);
if(m == n) // one stone per pile
return n % 2 == 0 ? "First" : "Second";
// if here, m < n
return n % 2 == 0 ? (m % 2 == 0 ? "Second" : "First") : "First";
}
但这导致测试用例{2,1,3}
失败,导致"Second"
。
我尝试使用以下事实。
2
为2
,那么堆积中任意数量大于2
的宝石都会产生相同的结果。原因是因为如果它大于1
且玩家在该转弯时没有将桩缩小到ul li:first-child {
//some css
}
那么玩家基本上已经让他的对手转弯了。 然而,可能有些事我错了..
答案 0 :(得分:2)
我认为您的以下陈述是关闭的:
堆积中任何数量大于2的石头如果是2
,都会得到相同的结果
如果状态是{1,2,2}第一位玩家可以通过移除1石头获胜。如果状态是{1,2,3},则第一个玩家无法获胜。因此,如果石头的数量是2或3,则存在差异。
因为如果它大于2且玩家在该转弯时没有将桩缩小到1,那么玩家基本上会让对手转弯。
这是正确的,除了有时候“转向另一位玩家”,即通过转弯是“理想的”。
最优策略与二进制表示中每个堆中项目数的XOR有关。有关最佳解决方案和详细信息,请参阅https://en.wikipedia.org/wiki/Nim。