取(2堆)石子游戏(杭电2177)

取(2堆)石子游戏

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1175    Accepted Submission(s): 706


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
/*本题还是威佐夫博弈。
利用重要性质:不论什么自然数都包括在一个且仅有一个神秘局势中。

神秘局势即必败点,想要理解威佐夫博弈,在百度文库博弈入门有详解 */ /*核心思路:以m[k],n[k]为界限来分析,就是3种情况 (1)假设a>m[k]。b>n[k],自然的剩下的石子数量就是a[k],b[k]。 (2)假设a<m[k](b<n[k])。然后你就须要在m[k]之前寻找是不是有m[i]或者b[i]和a相等, 是不是有m[i]或者n[i]和b相等,当然了有的情况是不须要考虑的由于是不可能出现的。 (3)。假设a=m[k]。那么你就挂了。 */ #include<stdio.h> #include<math.h> int a[1000010]; int b[1000010]; int main() { int m,n,t,k,i; a[0]=0,b[0]=0; a[1]=2,b[1]=1; for(i=2;i<1000010;i++) //先打表。 { b[i]=i*(1+sqrt(5))/2; a[i]=b[i]+i; } while(scanf("%d %d",&m,&n)!=EOF&&(m+n)) { if(m<n); { t=m;m=n;n=t; } k=m-n; if(n==b[k]) { printf("0 "); continue; } else //核心思路的代码。 { printf("1 "); if(n<b[k]) { for(i=1;i<n;i++){ if(n==b[i]&&m>a[i]) printf("%d %d ",b[i],a[i]); if(m==a[i]&&n>b[i]) printf("%d %d ",b[i],a[i]); } } if(n>b[k]) { printf("%d %d ",b[k],a[k]); for(i=1;i<n;i++) { if(n==a[i]&&m>b[i]) printf("%d %d ",b[i],a[i]); if(n==b[i]&&m>a[i]) printf("%d %d ",b[i],a[i]); } } } } return 0; }



原文地址:https://www.cnblogs.com/yxwkf/p/5163693.html