POJ 2234: NIM博弈


——NIM博弈
原题传送门

Description

Here is a simple game. In this game, there are several piles of matches and two players.
The two player play in turn.
In each turn, one can choose a pile and take away arbitrary number of matches from the pile (Of course the number of matches, which is taken away, cannot be zero and cannot be larger than the number of matches in the chosen pile).
If after a player’s turn, there is no match left, the player is the winner.
Suppose that the two players are all very clear. ///“Very Clever”
Your job is to tell whether the player who plays first can win the game or not.

Data

Input
The input consists of several lines, and in each line there is a test case. At the beginning of a line, there is an integer M, which is the number of piles. Then comes M positive integers, which are not larger than 10000000. These M integers represent the number of matches in each pile.
Output
For each test case, output “Yes” in a single line, if the player who play first will win, otherwise output “No”.

	Sample Input
	2 45 45
	3 3 6 9
	Sample Output
	No
	Yes

1 <= M <=20

思路

这是一道NIM博弈的模板题.

NIM 博弈

描述

给定N堆物品,已知第i堆有Ai个,有两个人(下称甲乙),按照如下规则取物品:

  • 在每一轮中,玩家可以选择一个堆,并从该堆取走任意物品.
  • 取走物品的数量不可能为0,也不可能大于所选物品的数量~~(等于没说)~~.
  • 如果在玩家取走物品后,没有物品留下,那么此玩家胜.

已知甲先取,并且两个人都按照最佳策略取物品,问谁必胜.

建模

对于这样的博弈类题目,通常都是公平组合博弈.
也就是说,(1)局面和决策与玩家无关.
当然还有其他条件,比如(2)双方轮流行动,(3)不能行动者判为负.
像围棋,象棋,都不在范围之内.
那么,我们可以认定,NIM博弈属于公平组合博弈.
如果认为一般的NIM博弈太困难,可以考虑堆数(以下称T)<=2的情况.


对这个博弈分析,就可以得出以下性质:

  1. 如果有T=1,则先手(甲)胜.(显而易见,一次取完)

  2. 如果有T=2,那么:

    若A1等于A2,则后手(乙)胜,因为在甲在一堆取一些后,乙可以在另一堆取相同数量的物品,从而最后胜利.
    若A1不等于A2,则先手(甲)胜,因为甲先取完后,就变成了A1=A2的状态.

如果对这个简化的博弈进行分析,就可以得到:

  1. 如果甲取过后,乙在行最优策略下,仍无法取完(胜),那么甲必胜.
  2. 如果无论甲如何取,乙都能保证取完(胜),那么甲必败.

结论

由此扩展,可以得到一般公平组合博弈的性质:
//以下称两玩家为A,B,必胜的状态为必胜状态,必败的状态为必败状态

  1. 公平组合博弈的状态可以视为有向图.
  2. 如果A行动后,B面临必败状态,那么A的这个状态为必胜状态.
  3. 如果A无论如何行动,B都面临必胜状态,那么A的这个状态为必败状态.

请注意(2)(3)之间的区别.

分析

下面进入NIM博弈的正式分析.
我们将每个数Ai分解为二进制,对这些二进制数位进行分析.

  1. 如果这些位都是偶数,就是必败状态.
  2. 如果有一位是奇数,就是必胜状态.

(2)证明:当存在奇数位时,可以找到一种方案,使这些奇数位变成偶数位,从而根据性质2.必胜.
(1)可以用相同逻辑证明.
其实漏洞挺厉害的.
所以,这道题目的代码异常简单.

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,x,ans;
int main()
{
	//No arrays
	while (~scanf("%d",&n))
	{
		ans=0;
		for (int i=1;i<=n;i++) 
		{
			scanf("%d",&x);
			ans^=x;
		}
		if (ans==0) printf("No\n");
		else printf("Yes\n");
	}
	return 0;
}

感谢奆老关注 qwq ?

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值