CF1921E 题解
题意简述
爱丽丝和鲍勃在一个
两人由爱丽丝开始轮流行动,爱丽丝每次行动能将自己的棋子向左下、正下或右下移动,鲍勃每次行动能将自己的棋子向左上、正上或右上移动。注意不能将棋子移出棋盘外。
当有玩家将自己的棋子移到对方棋子的位置上时,该玩家获胜。若有玩家无法移动自己的棋子,那么游戏立即以平局结束。
两人都绝顶聪明,求出谁会获胜或告知平局。
思路
不妨设最开始两人的棋子都在同一列上,很显然若棋子行坐标之差为偶数,则先手必败。
证明:首先爱丽丝移到哪一列,鲍勃都可以跟上,最后行坐标之差为
那么再推广到不同列,因为两人绝顶聪明,所以知道自己若在同一列必然会输的一方,肯定会尽可能地躲避另一方,追求平局。在同一列必然会赢的一方也肯定会尽量追。
我们发现,能不能追到无路可躲(到棋盘边缘)的时候不是那么好求。
但是行数最多只有
具体实现时会有很多细节需要注意,接下来看代码。
Code
#include <iostream>
using namespace std;
void work()
{
int n, m, xa, ya, xb, yb;
scanf("%d%d%d%d%d%d", &n, &m, &xa, &ya, &xb, &yb);
if (xa > xb) //如果鲍勃已经在爱丽丝上方,那就肯定平局。
{
puts("Draw");
return;
}
int xc = xb - xa;
if (ya == yb)
{
if (xc & 1)
puts("Alice");
else
puts("Bob");
return;
}
if (xc & 1) // 爱丽丝追鲍勃
{
while (xa < xb)
{
if (yb < ya) // 往鲍勃的方向追
ya --;
else if (yb > ya)
ya ++;
else // 如果已经在同一列
{
puts("Alice");
return;
}
xa ++;
if (xa == xb && ya == yb)
{
puts("Alice");
return;
}
if (yb < ya && yb > 1) // 往反方向躲
yb --;
else if (yb > ya && yb < m)
yb ++;
xb --;
if (xa == xb && ya == yb)
{
puts("Alice");
return;
}
}
puts("Draw");
}
else // 爱丽丝躲鲍勃
{
while (xa < xb)
{
if (yb < ya)
{
if (ya < m)
ya ++;
}
else if (ya < yb)
{
if (1 < ya)
ya --;
}
else
{
if (xb - xa <= 1)
puts("Draw");
else
puts("Bob");
return;
}
xa ++;
if (xa == xb && ya == yb)
{
puts("Bob");
return;
}
if (yb < ya)
yb ++;
else
yb --;
xb --;
if (xa == xb && ya == yb)
{
puts("Bob");
return;
}
}
puts("Draw");
}
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
work();
return 0;
}