HDU 5754 Life Winner Bo 2016多校第三场1003

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5754

题意:给你一个n*m大小的棋盘,分别以国际象棋的国王、战车、骑士和皇后的走法从(1,1)走到(n,m),而且只能向右或者向下走,问谁有必胜的策略或者是两者平局。

题解:无论是哪一种移动,都可以注意到,如果从起点到某一个点有必胜的策略,那么再以必胜点作为起点可以走到下一个必胜点,也就是以小见大。

   一、对于王的走法,可以注意到3*3大小的棋盘,从(1,1)到(3,3)后手是有必胜的策略的,对于NM更大的情况,我们把横坐标每隔3、纵坐标每隔3的点都画出来,这些点都是符合后手胜的。因为无论先手怎么移动,后手都能重新移动到这些格子,直到到了终点)如果初始点不在这些点上,就必然是先手胜。因为先手可以立刻移动到上述的点。

   二、对于车的走法,注意到,如果目前的位置距离终点的x和y坐标差相等,一定是后手胜。(因为先手只能向下或者向右走一段路;无论他往哪里走,后手往另一维走相同的步数,依然保持这一样一种状态。)反之,先手必然能走到一处相等的位置,转化为上述问题,所以一定是先手胜。

   三、马的走法,在大多数情况下都是平局。在模3域下,某些地方会存在先后手赢。画图找规律。

   四、皇后的走法最为复杂,不过其实也就是一个威佐夫博弈。

   关于威佐夫博弈:http://baike.baidu.com/link?url=Xf_NMvP2GFcr93BAmCLsTqY6ULiseus-TLg0dgG_1yx1C-bzt0pSQAFOt0jMb6WvGwd9S_xIj6ZCtBIc0ygotbc9IglMjGcwHHD8nsohR-bIf5yNzG35AHD5xbhrhkSi)。

   我们可以将问题转化为:“有两堆石子,每次可以在一堆里取任意(非空)颗(相当于是车的走法),或者在两堆里取相同(非空)颗(相当于是象的走法),取到最后一颗石子的人获胜,问先后手谁有必胜策略。”为什么说是威佐夫博弈呢。

   其实仔细想一想就会明白这个走法产生的局面(画图更为清楚),先手从(1,1)开始走,那么第一步他可以到达任意一个x=1(或y=1,两者对称)的局面,那么我们看x=2的时候,(2,1)(2,2)是先手在第一步能到达的。然而(2,3)是后手的必胜点。那么根据前面所说我们在从(2,3)作为起点开始推可以知道,从(2,3)开始的第一步是可以到达坐标中带有2或者3的任意点(别忘了(3,2)与(2,3)等价),也就是说后手的下一个必胜点必定是从x=4(或y=4)开始的(而且x=4时必定有后手的必胜点),这里又是为什么呢?很简单,就是因为从(2,3)开始走,所有坐标中带有2或者3的所有局面先手都可以到达,而且先手只能去到坐标中带有4的部分局面。如图(把所有坐标+1即可得到本题局面):

    由此我们可以推知,皇后的走法,后手必胜点就是威佐夫博弈中的奇异局势,打表即可(也有必胜点的公式求法:一个奇异局势(ak,bk)为:ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,...n 方括号表示取整函数)

    这是本人对威佐夫博弈的一点点理解,还不够深入,欢迎吐槽!。

代码如下:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <cmath>
 7 using namespace std;
 8 
 9 const double phi=(1+sqrt(5.0))/2.0;
10 int t,ty;
11 int n,m;
12 int g[1005][1005];
13 int f[1005];
14 int vis[2][2005];
15 
16 int main()
17 {
18     int x,y;
19     for(int i=1;;i++)
20     {
21         x=phi*i;
22         y=x+i;
23         if(y>1000)
24             break;
25         f[x]=y;
26     }
27     scanf("%d",&t);
28     while(t--)
29     {
30         scanf("%d%d%d",&ty,&n,&m);
31         if(ty==1)
32         {
33             if(n%2&&m%2)
34                 puts("G");
35             else
36                 puts("B");
37             continue;
38         }
39         else if(ty==2)
40         {
41             if(n==m)
42                 puts("G");
43             else
44                 puts("B");
45             continue;
46         }
47         else if(ty==3)
48         {
49             if(n==m&&n%3==1)
50                 puts("G");
51             else if(max(n,m)%3==0&&max(n,m)-min(n,m)==1)
52                 puts("B");
53             else
54                 puts("D");
55         }
56         else
57         {
58             n--,m--;
59             if(n>m) swap(n,m);
60             if(f[n]==m)
61                 puts("G");
62             else
63                 puts("B");
64         }
65     }
66     return 0;
67 } 
原文地址:https://www.cnblogs.com/zhuyutian/p/5790765.html