题目描述:
两个人玩棋盘游戏,规则如下:1.棋盘上只有一枚棋子,先手和后手轮流移动棋子。2.棋子移动方向只能是向左(从(x,y)到(x-1,y))或者是向下(从(x,y)到(x,y-1))或者是左下(从(x,y)到(x-1,y-1)),每次只能在棋盘上移动一步。3.将棋子移动到(0,0)坐标的即为胜者(即下一位玩家不能再移动棋子)。现输入棋子的x,y坐标,在双方都采取最优策略的前提下,请输出胜者为先手或是后手。
样例1 :输入 1 1 输出 先手
样例2: 输入 124 654 输出 后手
分析:
本题有点类似于威佐夫博弈,但还是有很大差别。题目要求是每次只能移动一步。
那么,我们可以从棋子的移动方向这一点开始分析,既然只能向左,下,左下三个方向移动,那么当棋子处于左边界时就只能向下移动,当棋子处于下边界就只能向左移动,处于这两种情况的棋子就完全可以确定胜者为先手或是后手了,如图:
由于左边界和下边界是镜面对称的,我们只看下边界。可以看出x坐标处于奇数的先手必胜,处于偶数坐标的后手必胜。
我们已经把棋盘最外边界看出规律了。现在我们缩小范围,看下一层,如图:
为什么当y=1时或x=1时上的棋子胜者全部为先手呢?这当然是由棋子的移动方向来就决定的,比如处于(4,1)的棋子先手把棋子棋子移动到(4,0)的位置,先手变为了所谓的后手。棋子目前处于边界位置。轮到后手移动时已经无法修改棋局,棋局已经被先手控制,只能向左移动,最后只能是先手获胜。处于(5,1)的棋子先手也把左下棋子棋子移动到(4,0)的位置。同样是先手获胜。可以看出,轮到y=1时或x=1时进行移动的玩家可以操纵棋盘的局势。 这一点很重要。由于我们分析的情况是初始棋子全部在x=1或y=1时的,而这个时候先手都是以先手开始的,所以肯定都是先手胜。
现在我们看第三层:(如图)
还记得我们刚才说的吗?轮到y=1时或x=1时进行移动的玩家可以操纵棋盘的局势。那么当棋子初始在x=2或y=2时先手肯定不想让自己输,如果他向左下或向下移动到y=1时,后手移动时就可以操纵棋盘局势,先手必败。唯一的移动方向只能是向左
再向左也是有边界的,最多只能移动到x=2,移动到x=1时同样被后手操纵。我们先看先手向左移动一步后的情况,比如从(5,2)移动到(4,2),轮到后手移动了。后手也不会向左下或向下移动到y=1,这样棋局则被先手操纵了。所以也只能向左移动一步,当先手移动到(2,2)位置时。轮到后手了,后手若向下或向左移动到x=1或y=1位置时。棋局就被先手操纵了。若向左下移动也是先手必胜,可以看出当先手或后手移动到(2,2)点时必胜。而先手或后手为了避免自己不被局势操纵,又只能沿着x轴向左移动。这第三种情况与第一种情况一模一样,我们可以从其中看到点规律了,第三层与第一层的边界情况很像。
最后我们看第四层(如图):
遵循上一层提到的规律,我们可以这样推测第四层,轮到y=4时或x=4时进行移动的玩家可以操纵棋盘的局势。第三层可以看做是边界,第四层与第一层情况基本一样。我们可以推测初始棋子在y=4时或x=4时先手必胜。
很明显,规律已经出来了,每两层一个循环,一层为边界,一层用于局势转换。
以下是完整的棋盘模型:(如图)
可以看出如下规律:
当棋子所处x坐标或y坐标只要有一个为奇数时,先手必胜。否则后手必胜。
AC代码
#include<iostream>
using namespace std;
int main()
{
int a,b;
cin>>a>>b;
if(a%2==1||b%2==1)
cout<<"先手"<<endl;
else
cout<<"后手"<<endl;
}