这两天认识了几个组合游戏的基础模型,希望自己能更新下去。。
有两个盒子,一个装有 m 颗糖,一个装有 n 颗糖,表示为 (m, n) .
每次清空一个盒子,将另一个盒子里的糖转移一些过来,并保证两个盒子至少各有一颗糖。
最后进行转移糖者胜,无法转移糖者败。
m, n 都为奇数,先手败;m, n 至少一个为偶数,先手胜。
显然,初始状态为(1, 1),先手必败;
设 max(m, n) = 2,即初始状态为 (1, 2),(2, 1) 或 (2, 2),对于 (1, 2),(2, 1) 先手可以把 1 清空,然后将 2 分为 (1, 1) ,先手胜;对于 (2, 2) ,先手可以把其中一个 2 清空,然后将另一个 2 分为 (1, 1) ,先手胜。符合结论。
设 max(m, n) < k 均符合结论,当 max(m, n) = k :
设 m 与 n 至少一个为偶数(假设m是偶数),则将 n 清空,把 m 分为两个奇数 (a, b) ,由于max(a, b) < k ,因此(a, b) 必败,(m, n) 必胜(利用规则2);
设 m 与 n 均为奇数,则只能把其中一个数分为一个奇数 a ,一个偶数 b ,由于max(a, b) < k ,因此对于任何的方式分解出的(a, b) 均必胜,(m, n) 必败(利用规则1);
故 max(m, n) = k 符合结论。
故对于任意 (m, n) 结论成立。
有一个 m * n 的棋盘,棋盘的每一个格子用(x, y)表示,最左下角是(1, 1),最右上角是(m, n) ;
每次可以拿走一个方格,并拿走该方格右边与上边的所有方格。
谁拿到(1, 1)谁败。
当 m = n = 1,先手败;除此之外,先手均有必胜策略(先手胜)。
反证法:
假设后手能取得胜利,那么先手可以第一步拿走(m, n),若后续回合内后手通过拿走(x, y)达到了必胜状态,先手均可以第一步就拿走(x, y)来达到必胜状态。
故不存在后手必胜状态。
由于无法给出构造性证明,所以只能证明先手必胜,而不能给出广义的必胜策略。
桌上有 n 个数字:1~n。
两人轮流在选择一个桌上的数 x ,然后将 x 与 x 的约数都拿走。
拿去最后一个数的人胜出(无法选择数字的人失败)。
先手有必胜策略。(先手胜)
这个游戏是 chomp! 的思想的应用。
假设后手能取得胜利,那么先手可以第一步拿走 1,若后续回合内后手通过拿走 x 达到了必胜状态,先手均可以第一步就拿走 x 来达到必胜状态。
n 个物品堆成一堆。
两个人轮流从这堆物品中取物,规定每次至少取一个,最多取 m 个。
最后取光者得胜。(无法取者败)
如果 n % (m+1)≠0 ,则先手必胜。
如果 n=m+1 , 显然,先手无论取多少,后手均可以将剩余物品一次全取走,所以先手败。
如果 n=k∗(m+1) ,我们从后手的角度来考虑,设先手第一次取走 x 个物品,那么后手只要再取走 m+1−x 个,此时剩余物品数量变为 (k−1)(m+1) 个,一直重复这个步骤,就可以回到先手面临 n=m+1 的局面,所以还是先手败。相当于进行了k次 n=m+1 的游戏。
如果 n=k∗(m+1)+s ,先手一开始取走 s 个物品,那么后手就会面临 n=k∗(m+1) 的局面,所以先手胜。
结论得证。
有一个游戏,在一个n*m的矩阵中起始位置是(1, m),走到终止位置(n, 1);游戏规则是只能向左,下,左下方向移动一步,先走到终点的为获胜者。(HDU 2147,总共有 n + m 的距离要移动,一次最多移动 2 的距离,故判断 (n + m)%2 是否为 0 即可)。
bash博弈变形1——减法博弈:
两个人轮流报数,每次至少报一个,最多报十个,谁能报到100者胜。(先手必胜,第一次报1,类似:HDU 2149)
有一个由n个石子组成的石子堆,两名玩家轮流从中拿走石子,每次拿走石子的个数只能是集合S中的数。拿走最后一枚石子的玩家获胜。(状态转移即可)
bash博弈变形2:初始状态下有石子n个,除最后一次外其他每次取物品个数必须在[p,q]之间,最后一次取硬币的人输。(HDU 2897)
这题状态稍微复杂一些,并且胜负条件与之前相反,一般bash博弈里每次取个数可以看作在[1,m]之间,胜负手判断为 n % (1+m) ,因此我们可以猜想每次取[p,q]的胜负手判断为 n % (p+q) ,通过验证猜想我们可以发现如下策略:
//HDU 2897
#include
using namespace std;
int main()
{
int n , p , q ;
while ( cin >> n >> p >> q ) {
if ( n % ( p + q ) <= p && n % ( p + q ) )
puts( "LOST" ) ;
else
puts( "WIN" ) ;
}
return 0;
}
有两堆石子,一堆有 m 个,另一堆有 n 个。
双方轮流取走一些石子,合法的取法有如下两种:
1. 在一堆石子中取走任意多颗;
2. 在两堆石子中取走相同多的任意颗.
取走最后一颗石子的人为赢家。
(1,2) (1,2) 与 (2,1) (2,1) 视为同一状态,
第 k 个必败状态是 (\lfloor\frac{\sqrt 5 +1}{2}*k \rfloor+k,\lfloor\frac{\sqrt 5 + 1}{2}*k \rfloor) (⌊5√+12∗k⌋+k,⌊5√+12∗k⌋) 。
拓展性质:
令(m(k),n(k))=(\lfloor\frac{\sqrt 5 + 1}{2}*k \rfloor+k,\lfloor\frac{\sqrt 5 + 1}{2}*k \rfloor) (m(k),n(k))=(⌊5√+12∗k⌋+k,⌊5√+12∗k⌋) ,则 m(k) 也表示前 k 个必败状态中没出现的自然数。
每个自然数都会出现在必败状态中且仅会出现一次。
//HDU 1527 模板题
#include
using namespace std;
int main()
{
int a , b ;
while ( cin >> a >> b ) {
if ( a < b ) swap( a, b ) ;
int k = a - b ;
int n = (int)( k * ( sqrt(5.0) + 1.0 ) / 2 ) ;
bool win = ( n != b ) ;
cout << win << endl ;
}
return 0;
}
还是打表吧。。
const int N = 50 ;
bool win[100][100] ;
void init()
{
memset( win , false , sizeof win ) ;
for ( int i = 1 ; i <= n ; i++ ) win[i][i] = true ;
for ( int i = 1 ; i <= n ; i++ ) {
for ( int j = i+1 ; j <= n ; j++ ) {
if ( !win[i][j] ) {
for ( int k = j + 1 ; k <= n ; k++ )
win[i][k] = win[k][i] = true ;
for ( int k = i + 1 ; k <= n ; k++ )
win[k][j] = win[j][k] = true ;
for ( int k = 1 ; k <= n ; k++ )
win[i+k][j+k] = win[j+k][i+k] = true ;
}
}
}
for ( int i = 1 ; i <= n ; i++ )
for ( int j = i ; j <= n ; j++ ) {
if ( !win[i][j] ) cout << i << ' ' << j << endl ;
}
}
有一堆个数为 n >= 2 的石子。
双方轮流取石子,满足以下条件:
1. 先手不能在第一次把所有的石子取完;
2. 之后每次可以取的石子数介于 1 到对手刚取的石子数的 2 倍之间(包含 1 和对手刚取的石子数的 2 倍)。
取走最后一个石子的人为赢家。
如果 n 是斐波那契数,则后手胜;反之,先手胜。
\\HDU 2516 模板题
#include
using namespace std;
const string win[2] = { "Second win" , "First win" } ;
long long fib[100] ;
int init()
{
fib[0] = 1 ; fib[1] = 1 ;
for ( int i = 2 ; i < 100 ; i++ ) {
fib[i] = fib[i-1] + fib[i-2] ;
if ( fib[i] > ( 1LL << 35 ) ) return i ;
}
return 100 ;
}
int main()
{
int n ; int len = init() ;
while ( cin >> n && n ) {
int ok = 1 ;
for ( int i = 0 ; i <= len ; i++ ) {
if ( fib[i] == n ) {
ok = 0 ;
break ;
}
}
cout << win[ok] << endl ;
}
return 0;
}
Zeckendorf定理:任何正整数可以表示为若干个不连续的 Fibonacci 数之和。
先手必须从 <= n / 3 的数量开始取(例如第一次取的数量 > n/3,那么后手可以直接取完所有剩下石子)
于是。。。太绕了!
还是请看Acdream大神的吧。。http://blog.csdn.net/acdreamers/article/details/8586135
有三堆各若干个物品,两个人轮流从某一堆取任意多的
物品,规定每次至少取一个,多者不限,最后取光者得胜。
介绍这个游戏的太多了。。偷个懒
具体解法就是异或异或!