Yes
#include<cstdio> #include<iostream> using namespace std; const int maxn=1e7+10; int a[maxn],n,m; inline int read(){ char ch=getchar(); while(ch!='0'&&ch!='1') ch=getchar(); return ch-'0'; } int main(){ int T; scanf("%d",&T); while(T--){ int k=0,cnt=0;//cnt记录1的个数 scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) cnt+=(a[k++]=read()); if(cnt%2) puts("No"); else { if(n==1||m==1) { //此时手动模拟即可 //在这里要注意k<3的情况 if(k<3) if(cnt) puts("No"); else puts("Yes"); else { for(int i=0;i<k-3;i++) if(a[i]) { a[i+1]^=1; a[i+2]^=1; a[i+3]^=1; } if(a[k-1]||a[k-2]||a[k-3]) puts("No"); else puts("Yes"); } } else if(n==2&&m==2) { a[0]=a[0]+a[1]+a[2]+a[3]; if(a[0]==0||a[0]==4) puts("Yes"); else puts("No"); } else puts("Yes"); } } return 0; }
首先这题要求 O(nm) 的复杂度,这是读入复杂度,所以这启发我们去找规律,而不是去搜索
我们可以通过某些方块的奇怪组合来组成一些简单的操作 操作1: + = 操作2: + = 操作3: + = 当然,上面并没有把所有情况拼出,只是说明在2*3时可以拼出两块任意位置。 上述操作都可以认为是将某个黑格平移,或者是两两抵消 但是有条件限制:需要一个 2*3 的空间 所以当棋盘上能创造一个 2*3 的空间时,只需要判断黑格个数的奇偶性即可,奇数为 No,偶数为 Yes 那么假如棋盘小于 2*3 呢? 两种情况:2*2 和 1*? 2*2 只需要考虑2*2的正方形方块即可 1*? 的情况我们只能用 1*4 的方块,所以我们可以用贪心的解法,就每次选取最左端的黑格,以此作为 1*4 方块的左侧进行黑白反转,重复进行直到无法将 1*4 放置在棋盘上,这时候再判断棋盘是否为全白即可