HDOJ 1907

大概看了一种博弈问题的变化题,左边这个链接讲解的还是不错的。

Nim博弈大家都知道,就是有N堆石子,两人轮流取,每次在一堆中取任意个,取到最后一个的胜利。

现在的变化是,取到最后一个的算失败。

这怎么做?

首先我们定义:

对于N堆石子,每堆的个数为Ai(1<=i<=N)。

设C=A1^A2^...^An;

若C=0,则状态设为T,称为利他态。反之,设状态为S,称为利己态。

孤单堆,该堆的石子数量为1.

充裕堆,该堆的石子数量大于1.

在T态中,T2为充裕堆数量>1,T0为充裕堆数量为0.(T1不存在)。

在S态中,S2为充裕堆数量>1,S1为充裕堆数量为1,S0为充裕堆数量为0;

定理1:T0为必胜态。

由于仅存在孤单堆,且C=0,即有偶数个孤单堆,故为必胜点。反之S0为必败点。

定理2:S1为必胜态。

有且仅有一个充裕堆,则,若有奇数个孤单堆,则将此充裕堆取完,则对方面临S0态,必败,故此法可取胜。

                                          若有偶数个孤单堆,则将此充裕堆取成孤单堆,对方仍旧面临S0态,故此法仍胜。

定理3:T2只能转化为S2或S1。

首先T态必须变为S态,充裕堆不能一次由2变为0,故不能变为S0,得证。

定理4:S2不能一次转化为T0。

定理5:S2可以一次转化为T2。

由于C的最高位为1,则取Ai中同最高位的At。

设x=At^C。则

A1^A2^....^x^...^An=

A1^A2^....^At^C^...^An=

A1^A2^....^An^A1^A2^...^An=0;为T态.

定理6:S2采取合理的措施,必胜。

任意S2都可以转化为T2,T2能转化为S1或S2。这样逼迫队手由T2转S1,抱持必胜态。

故整个状态变换为:

(T2->)S2->T2->S2->.....->T2->S1->T0->S0->....->T0;


#include<iostream>
using namespace std;

int main()
{
 	int T;
 	scanf( "%d",&T );
 	while( T-- )
 	{
	 	   int n;
	 	   scanf( "%d",&n );
	 	   int rec[50];
	 	   int sin=0,mul=0,xo=0;
	 	   for( int i=0;i<n;i++ )
	 	   {
	 	   		scanf( "%d",&rec[i] );
	 	   		rec[i]>1?mul++:sin++;
	 	   		xo^=rec[i];
		   }
	   	   if( (mul==1) || (mul==0&&xo==0) || (mul>1&&xo) )
	   	   	   printf( "John\n" );
	   	   else
	   	   	   printf( "Brother\n" );
  	}
 	return 0;
}


你可能感兴趣的:(HDOJ 1907)