【CCPC-Wannafly Winter Camp Day4 (Div1) F】小小马(分类讨论)
大致题意: 给你一张\(n*m\)的棋盘,问你一匹马在两个点中是否存在一条经过黑白格子数目相等的路径。
简化题目
首先,我们来简化一下题目。
考虑到马每次走的时候,所经过的格子的颜色必然发生变化,因此黑白格子数目相等这个条件就变成了起点和终点颜色是否相同。
当颜色相同时,我们就可以直接输出\(No\)了。
而接下来的问题就变成了:一匹马是否能从一个点到达另一个点。
在此之前,我们先默认\(n\le m\)(不满足条件\(swap\)即可)。
当\(n=1\)时
此时,马完全无法移动,因此直接输出\(No\)。
当\(n=2\)时
此时,马每次必然只能从某一行跳至另外一行。
先考虑起点与终点在同一行的情况,这肯定是不合法的。
因为马每次会跳至另一行,所以需偶数次才能保持在同一行。
而这样一来起点与终点颜色必然一样,在前面就已经被判掉了,无须再讨论。
那么只需考虑起点与终点不在同一行的情况。
简单画图可得,若合法,则此时起点与终点纵坐标在模\(4\)之后差值绝对值必然为\(2\)。
因此,对于\(n=2\)的情况,判断起点与终点纵坐标在模\(4\)之后差值绝对值是否为\(2\)即可得出答案。
当\(n=m=3\)时
通过简单画图,可以发现,周围一圈的马,无论如何都跳不到中间\((2,2)\)这一格子上。
同理,\((2,2)\)这一格子上的马也跳不到周围一圈的格子上。
所以,只需判断起点与终点是否存在某一个为\((2,2)\)即可。
其余情况
必定有解,输出\(Yes\)。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define swap(x,y) (x^=y^=x^=y)
#define abs(x) ((x)<0?-(x):(x))
using namespace std;
int n,m,sx,sy,ex,ey;
int main()
{
if(scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&ex,&ey),((sx^sy)&1)==((ex^ey)&1)) return puts("No"),0;//若同色,输出No
if(n>m&&(swap(n,m),swap(sx,sy),swap(ex,ey)),n==1) return puts("No"),0;//若n=1,输出No
if(n==2&&abs(sy%4-ey%4)^2) return puts("No"),0;//若起点与终点纵坐标差值的绝对值在模4之后不为2,输出No
if(n==3&&m==3&&((sx==2&&sy==2)||(ex==2&&ey==2))) return puts("No"),0;//若n=m=3且起点与终点存在某一个为(2,2),输出No
return puts("Yes"),0;//其余情况输出Yes
}
待到再迷茫时回头望,所有脚印会发出光芒