JS技术

hdu 2177 取(2堆)石子游戏(威佐夫博奕(Wythoff Game)) - 若忆_star - 博客频道 - C

字号+ 作者:H5之家 来源:H5之家 2015-12-14 19:07 我要评论( )

应用比较耗资源的话,tomcat启动时会报内存溢出的错误,修改方法如下:用vi命令打开tomcat安装目录/bin下的catalina.sh文件在该文件的第一行(具体在:cygwin=fa

题目链接:?pid=2177

取(2堆)石子游戏

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1649    Accepted Submission(s): 993



Problem Description

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

 


Author

Zhousc

 


Source

ECJTU 2008 Summer Contest

 


Recommend

lcy   |   We have carefully selected several similar problems for you:  2176 2180 1536 1850 1527 


题目大意:有两堆石子,两人轮流取石子,对于取石子有两种取法,1、从两堆石子中同时取出相同数量的石子,2、只从一堆中取任意数量的石子,另外一堆不变,直至不能取的人为输。

解题思路:

下面各种大神博弈中的一种,定义如下:

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

对比可以发现,神相似。

列出如下奇异局势:

k:(a,b)

0:(0,0)

1:(1,2)

2:(3,5)

3:(4,7)

4:(6,10)

...

可以看出,a0=b0=0,ak是未在前面出现过的最小自然数,而 bk= ak + k,奇异局势有如下三条性质:

1、任何自然数都包含在一个且仅有一个奇异局势中。
    由于ak是未在前面出现过的最小自然数,所以有ak > ak-1 ,而 bk= ak + k > ak
-1 + k-1 = bk-1 > ak-1 。所以性质1。成立。
 2、任意操作都可将奇异局势变为非奇异局势。
    事实上,若只改变奇异局势(ak,bk)的某一个分量,那么另一个分量不可能在其
他奇异局势中,所以必然是非奇异局势。如果使(ak,bk)的两个分量同时减少,则由
于其差不变,且不可能是其他奇异局势的差,因此也是非奇异局势。
3、采用适当的方法,可以将非奇异局势变为奇异局势

怎样判断是否面临奇异局势呢?有下面这个公式

ak =[k(1+√5)/2],bk= ak + k  (k=0,1,2,…,n 方括号表示取整函数)


详见代码。

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int main() { int a,b; while(scanf("%d%d",&a,&b),a||b) { if(a>b) swap(a,b); if(a==0) //无论b值是什么,一定赢。因为一次性可以把b所有石头取完,使对方面临奇异局势 { printf("1\n0 0\n"); continue; } int k=b-a;//差值表示第几个奇异局势 int aa=k*(1.0+sqrt(5.0))/2;//根据公式求得该个奇异局势的a值 if(aa==a)//面临该个奇异局势必输 { printf("0\n"); continue; } printf("1\n");//其他情况一定赢 int bb=aa+k;//aa和bb是奇异局势,即石子的剩余情况。 if(a-aa==b-bb&&a>aa)//判断是否可以取相同得使石子数是对方面临奇异局势 printf("%d %d\n",aa,bb); k=2*a/((1+sqrt(5.0)))+1;//只取b,a不变,根据a的值利用公式得到k的值,k为第几个 bb=a+k;//根据次数k和a得到奇异局势的b值 aa=k*(1.0+sqrt(5.0))/2;//根据次数k得到奇异局势的a,来验证不变的a是否就是奇异局势的a值 if(aa==a&&b>bb) printf("%d %d\n",a,bb); k=2*a/(3+sqrt(5.0))+1;//只取b,a不变,根据a的值利用公式得到k的值,k为第几个!!与上面不同的a的位置,上面将a看成是奇异局势的a,现在将a看成的是奇异局势的b,其他均相同 bb=a; aa=k*(1.0+sqrt(5.0))/2; if(bb-k==aa) printf("%d %d\n",aa,a); k=2*b/(3+sqrt(5.0))+1;//只取a,b不变,根据b的值利用公式得到k的值,k为第几个 bb=b; aa=k*(1.0+sqrt(5.0))/2; if(bb-k==aa&&aa<=a&&a!=b) printf("%d %d\n",aa,b); } return 0; }

  • 上一篇博弈总结
  • 顶 2 踩 0

    我的同类文章

    猜你在找

    查看评论

    * 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

    个人资料


    qiqi_skystar

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 【OpenCV入门教程之三】 图像的载入,显示和输出 一站式完全解析 - 【C++游戏编程】微软最有价值专家—毛星云(浅

      【OpenCV入门教程之三】 图像的载入,显示和输出 一站式完全解析 -

      2015-12-13 10:14

    • Javascript模拟游戏中的弹出菜单效果 _javascript教程教程

      Javascript模拟游戏中的弹出菜单效果 _javascript教程教程

      2015-10-10 09:18

    • javascript制作贪吃蛇游戏_Javascript教程

      javascript制作贪吃蛇游戏_Javascript教程

      2015-10-01 14:08

    • Javascript制作钻石棋游戏_Javascript教程

      Javascript制作钻石棋游戏_Javascript教程

      2015-09-26 11:10

    网友点评