阶梯博弈(历届试题 高僧斗法 )

 

 我们可以将人从前往后两两配对,在同一对人中,如果对手移动后一个人,你总能移动前一个相同的步数,

所以一对人的后一个人与后面一对人的前一个人有多少台阶是没有影响的。

所以只要考虑同一对人之间有多少台阶就行了,这样就转化为了Nim游戏。

如图: a与b配对, c与d配对 ,那么b与c之间的台阶是没有影响的,无论b怎么移动,a总能够移动相同的步数

 

如果该Nim游戏为必胜,那么我们只要移动配对人中的前一人就好了,如果对手想要破坏这种Nim游戏,即他想移动配对中的后一人,那么我们可以移动前一对的后一个人

使得依然保持Nim游戏的局势。

如果Nim游戏必败,那么先手者可能想破坏Nim游戏,那么后手者按照刚才的方式保持Nim游戏即可。

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int N = 100 + 10;
 4 int a[N],b[N];
 5 int main()
 6 {
 7     int n = 0,i,j,k,sum = 0;
 8     while(scanf("%d",&a[n])!=EOF)
 9         n++;
10     for(i=1; i<n; ++i)
11         b[i-1] = a[i] - a[i-1] - 1;
12     for(i=0; i<n-1; i+=2)
13         sum ^= b[i];
14     if(sum==0)
15         printf("-1\n");
16     else
17     {
18         //枚举第i个人移动j步,使得剩下的局面异或等于0,
19         for(i=0; i<n-1; ++i)
20             for(j=1; a[i]+j<a[i+1]; ++j)
21             {
22                 
23                 b[i] -= j;
24                 if(i!=0)
25                     b[i-1] += j;
26                 
27                 sum = 0;
28                 for(k=0; k<n-1; k+=2)
29                     sum ^= b[k];
30                 if(sum==0)
31                 {
32                     printf("%d %d\n",a[i],a[i]+j);
33                     break;
34                 }
35                 b[i] += j;
36                 if(i!=0)
37                     b[i-1] -= j;
38                 
39             }
40     }
41     return 0;
42 }

 

  

posted @ 2015-03-26 10:34  justPassBy  阅读(4012)  评论(1编辑  收藏  举报