传送门
4 1 5 5 2 5 5 3 5 5 4 5 5
G G D B
题目大意:
有4种操作分别是:
1.king.
2.rook(castle).
3.knight.
4.queen.
然后这些操作对应的是国际象棋里面的一些操作(具体操作可以百度) 然后现在我们站在(1,1)点,要去往(N,M)点,按照国际象棋操作的时候只能往右或者往下走,然后有两个人进行按照规则进行操作,谁最先到达(N,M)点谁就胜出。
解题思路:
我们依次分析每一种棋子。
①王。
首先注意一个3*3的棋盘,开始在(1,1),问走到(3,3)谁有必胜策略。
穷举所有情况,容易发现这是后手赢。
对于 N 和 M 更大的情况,我们把横坐标每隔3、纵坐标每隔3的点都画出来,这些点都是符合后手胜的。
(因为无论先手怎么移动,后手都能重新移动到这些格子,直到到了终点)
如果初始点不在这些点上,就必然是先手胜。因为先手可以立刻移动到上述的点。
②车。
注意到,如果目前的位置距离终点的 x 和 y 坐标差相等,一定是后手胜。
(因为先手只能向下或者向右走一段路;无论他往哪里走,后手往另一维走相同的步数,依然保持这一样一种状态。)
反之,先手必然能走到一处相等的位置,转化为上述问题,所以一定是先手胜。
③马。
同样还是画图可以得到规律。
在大多数情况下都是平局。在模3域下,某些地方会存在先后手赢。
④皇后。
画画图后,我们可以将问题转化为:
“有两堆石子,每次可以在一堆里取任意(非空)颗(相当于是车的走法),或者在两堆里取相同(非空)颗(相当于是象的走法),取到最后一颗石子的人获胜,问先后手谁有必胜策略。”这就是一个威佐夫博弈,需要注意的是我们应该已经在n–,m–的基础上的威佐夫博弈,因为我们站在(1,1)点。然后根据公式就行了。
My Code:
#include
#include
#include
#include
using namespace std;
int main()
{
int T;
int N,M,type;
cin>>T;
while(T--)
{
scanf("%d%d%d",&type,&N,&M);
if(type==1)
{
if(N>M) swap(N,M);
if(N%2==0||M%2==0) puts("B");
else puts("G");
}
else if(type==2)
{
if(N!=M) puts("B");
else puts("G");
}
else if(type==4)
{
if(N>M) swap(N,M);
N--,M--;
int tmp = (int)((1.0*sqrt(5.0)+1)/2*(M-N));
if(tmp == N)
puts("G");
else
puts("B");
}
else if(type==3)
{
if(N>M) swap(N,M);
if(N==M&&N%3==1) puts("G");
else if((N+1)==M&&M%3==0) puts("B");
else puts("D");
}
}
return 0;
}