ACM 博弈专题(5种模板)

()巴什博弈(BAsh Game)

题目模板

  • 只有一堆n个物品
  • 两个人轮流取,每次只能取1~m个物品,谁先取完,谁胜利;(n,m是输入的随机数)

解题思路

  1. n = m + 1 时 第一个取的人不可能获胜;
  2. n = k*(m + 1) + r 时           (k,r,s都是未知的整数)

    先取者拿走 r 个,那么后者再拿(1~m)个

    此时 n =(k-1)*(m+1)+s

    先取者再拿走s 个 最后总能造成 剩下n=k*(m+1) 的局面

    若n=k*(m+1) 那么先取者必输

  3. 若n=k*(m+1) 那么先取者必输

求解巴什博弈函数

int Bash_Game(int n,int m)//是否先手有必赢策略
{
    if (n%(m+1)!=0)
	    return 1;
    return 0;
}

样题:HDU 2147 kiki's game            HDU 2149 Public Sale          HDU 1846 Brave Game       HDU 2188 悼念512汶川大地震遇难同胞——选拔志愿者

 

 

()威佐夫博奕(Wythoff's game)

题目模板

  • 有两堆各若干个
  • 两个人轮流从某堆或同时从两堆取同样多的物品
  • 规定每次至少取一个,多者不限,最后取光的人胜利

解题思路

  • 两堆石子的状态为 [a,b] (满足a<=b)
  • 当 a=(k*(√5+1)/2), b=a+k 时满足奇异局势,那么则先手输,反之则先手赢

求解威佐夫博奕函数

int Wythoff_Game(int a,int b)//b要大于a
{
    double x=(1+sqrt(5))/2;
    int n=b-a;
    if(a==(int)(x*n))
        return 1;
    return 0;
}

样题:HDU 1527 取石子游戏           HDU 2177 取(2堆)石子游戏

 

 

() 尼姆博奕(Nimm's Game)

题目模板

  • 有多堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

解题思路

  • 用0与每个数异或,如最后结果为0,则后手胜

  • 设一数组a[n][m],令sum=0

  • 循环与数组每一个数据异或(sum^=a[i][j])

  •  sum最后等于0则后手胜

​​​​​​​求解尼姆博弈函数

a[m]每堆物品的数量  sum=0

int Nimm_Game(int n,int m)//n堆物品,m个物品
{
    for(int i=0;i<n;i++)
	    for(int j=0;j<m;j++)
		    sum = sum ^ a[i][j];
	if(sum == 0)
		return 0;
	return 1;
}

样题:HDU 1850 Being a Good Boy in Spring Festival

           HUD 1907 John        HDU 2509 Be the Winner

           HDU 1849 Rabbit and Grass

 

 

(四) 斐波那契博弈

题目模板

  • 有一堆个数为n的石子,游戏双方轮流取石子,
  • 满足:
  • 先手不能在第一次把所有的石子取完;
  • 之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间(包含1和对手刚取的石子数的2倍)

求解斐波那契博弈函数 f[50]

int Fib_Game(int n)
{
	f[1]=1;f[2]=1;
	for(int i=3;i<=50;i++)
		f[i] = f[i-1] + f[i-2];
	if( 数组f 中包含 n )
		return 1;//先手赢
	return 0;
}

样题:HDU 2516 取石子游戏

 

 

(五) 环形博弈

题目模板

  • n个石子围成一个环,每次取一个或者取相邻的2个(每个石子有序号)

​​​​​​​求解

  • 石子数<=2先手赢,否则后手赢
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章