码迷,mamicode.com
首页 > 其他好文 > 详细

威佐夫博弈

时间:2018-08-15 00:36:34      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:规则   就是   stdio.h   2.0   div   现在   mil   不同   ios   

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

a堆和b堆的个数用(a,b)表示

奇异局势:面对的时候,就是输家,比如(0,0),(1,2),(3,5),(4,7),(6,10)...

举例(0,0),规则上说取光者胜,轮到你的时候是(0,0),说明你输了。

举例(1,2),如果拿走一个,变成(1,1)或者(0,2),对手可以同时从两堆拿1个或者b堆拿2个,你都会输,如果拿走两个,变成(0,1)或者(1,0),对手随便拿走一个,你都会输。面对(1,2),必输。

举例(3,5),如果拿走一个,变成(2,5)或者(3,4),对手可以拿走b堆2个变成(2,1),让你面对奇异局势,也可以同时从a、b堆拿走2个,变成(1,2)让你面对奇异局势。如果拿走2个,可以变成(1,5),(2,4),(3,2),根据规则对手可以变成奇异局势(1,2),(2,1),(1,2)。必输...

任何非奇异局势都可以转变成奇异局势,先手面对的如果是奇异局势必输,如果不是奇异局势必赢。那么如何判断奇异局势呢?a =[k(1+√5)/2],b= a + k (k=0,1,2,...n 方括号表示取整函数)

当k=0时,有(0,0)

当k=1时,有(1,2)

当k=2时,有(3,5)

当k=3时,有(4,7)

当k=4时,有(6,10)

......

观察一下可以发现,每个自然数只出现过一次,并且奇异局势的两个数的差就是k值,所以只要判断a是否符合公式就可以了。

题目:

 

有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。如果你胜,你第1次怎样取子? 

Input

输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,且a<=b。a=b=0退出。 
Output

输出也有若干行,如果最后你是败者,则为0,反之,输出1,并输出使你胜的你第1次取石子后剩下的两堆石子的数量x,y,x<=y。如果在任意的一堆中取走石子能胜同时在两堆中同时取走相同数量的石子也能胜,先输出取走相同数量的石子的情况. 
Sample Input

1 2 
5 8
4 7
2 2
0 0

Sample Output

0
1
4 7
3 5
0
1
0 0
1 2
代码:
#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
const double sq=(1+sqrt(5.0))/2.0;///浮点数再取整

int main()
{
    int a,b,c;
    while(cin>>a>>b&&(a+b))
    {
        c=b-a;
        if( a==(int)(c*sq) && b==a+c )
            cout<<0<<endl;
        else
        {
            cout<<1<<endl;
            for(int i=1;i<=a;i++)///从两边那走一样多的石头
                if( a-i==(int) (c*sq) )///(int)(c*sq)对乘积整体取整
                printf("%d %d\n",a-i,b-i);

            for(int i=1;i<=b-a;i++)///从b堆拿走石头到b堆和a堆一样多,a比b少
                if( a==(int)  ((b-i-a)*sq)    )
                printf("%d %d\n",a,b-i);

            b=a;                    ///把b的石头数置为a,然后从a堆中拿,a还是比b少

            for(int i=1;i<a;i++)
                if( a-i==(int) ((b-a+i)*sq) )
                printf("%d %d\n",a-i,b);
        }
    }
    return 0;
}

 

威佐夫博弈

标签:规则   就是   stdio.h   2.0   div   现在   mil   不同   ios   

原文地址:https://www.cnblogs.com/shoulinniao/p/9478868.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!