递推/思维 Codeforces Round #693 (Div. 3) F题
题意:给一个2 * n 的方格,要求用 1 * 2 的骨牌,横着或者竖着放,铺满整个方格。
其中有一些被黑色方块阻挡,不能放骨牌 , 问是否可行?
解析:
首先,如果黑色堵块为奇数个,直接输出NO
考虑 整个方格 第一列
如果两行都是空的
那么考虑第二列的几种情况:
- 第二列也是空的,那么第一列可以竖着放。
- 第二列有一个方格被堵住了,那么第一列只能竖着放
- 第二列有两个方格都被堵住了,那么第一列也只能竖着放
所以第一列如果两行都是空的,竖着放就好。接下来继续往后考虑即可。
如果第一列两行都被堵住,同样继续考虑后面的即可。
如果第一列只有一行被堵住,则只能在没堵住的那一行放一个横着的骨牌,并且如果下一列如果仍然两行都是空的话,则又继续在没堵住的一行放一个横着的骨牌,直到某个位置也只有一行被堵住,没堵住的那一行正好可以放得下横着的骨牌,那就正好全部凑满了,继续考虑下一对即可。
这里可以根据前后两个只有一行被堵住的列的坐标差的奇偶性来判断,横坐标相减为奇数,则被堵住的行号应该相同。否则,应该不同。并且要保证第奇数个黑格子不与其前一个在同一列
int t,n,m;
struct node{
int x,y;
bool operator<(const node &t)const{
if(y == t.y) return x < t.x;
return y < t.y;
}
}a[N];
void solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&a[i].x,&a[i].y);
}
if(m & 1){
puts("NO");
return;
}
sort(a+1,a+1+m);
for(int i=2;i<=m;i++){
if(i & 1){
if(a[i].y == a[i-1].y){
puts("NO");
return;
}
}else{
int tmp1 = (a[i].y - a[i-1].y) % 2;
int tmp2 = abs(a[i].x - a[i-1].x);
if(tmp1 == tmp2){
puts("NO");
return;
}
}
}
puts("YES");
}
int main(){
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}