分析:假设n>=m,m为1,2单独讨论下,否则可以用第二行第一个把所有黑块搞到2x2的格子里,不断用凸出来的那个角一列一列把黑的变白就行了。然后只要黑色有偶数块都可以构造出来。复杂度O(nm)
#include <iostream> #include <cstring> #include <cstdio> using namespace std; class Board{ public: char **a; int n, m; void init(int _n, int _m){ n = _n, m = _m; a = new char*[n]; for(int i = 0; i < n; i++) a[i] = new char[m]; } Board(){} Board(int _n, int _m){ init(_n, _m); } ~Board(){ for(int i = 0; i < n; i++) delete[] a[i]; delete[] a; } void print(){ for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++) cout<<a[i][j]; cout<<endl; } } }; void inline change(char &a){ a = '1' + '0' - a; } inline void changex(char **a, int n, int m, int x, int y){ if(y == 0){ change(a[x][y]); change(a[x-1][y]); change(a[x-1][y+1]); change(a[x-2][y+1]); }else{ change(a[x][y]); change(a[x-1][y]); change(a[x-1][y-1]); change(a[x-2][y-1]); } } inline void changey(char **a, int n, int m, int x, int y){ if(x == 0){ change(a[x][y]); change(a[x][y-1]); change(a[x+1][y-1]); change(a[x+1][y-2]); }else{ change(a[x][y]); change(a[x][y-1]); change(a[x-1][y-1]); change(a[x-1][y-2]); } } bool solve(char **a, int n, int m){ if(n == 2 && m == 2){ if(a[0][1] != a[0][0] || a[1][0] != a[0][0] || a[1][1] != a[0][0])return false; return true; }else if(n <= 2 && m <= 2){ for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) if(a[i][j] == '1')return false; return true; } else if(n == 1){ while(m >= 4){ if(a[0][m-1] == '1'){ change(a[0][m-1]);change(a[0][m-2]); change(a[0][m-3]);change(a[0][m-4]); } m--; } if(a[0][0] == '1' || a[0][1] == '1' || a[0][2] == '1')return false; else return true; }else if(m == 1){ while(n >= 4){ if(a[n-1][0] == '1'){ change(a[n-1][0]);change(a[n-2][0]); change(a[n-3][0]);change(a[n-4][0]); } n--; } if(a[0][0] == '1' || a[1][0] == '1' || a[2][0] == '1')return false; else return true; } while(m >= 3){ for(int i = 0; i < n; i++) if(a[i][m-1] == '1')changey(a, n, m, i, m-1); m--; } while(n >= 3){ for(int i = 0; i < m; i++) if(a[n-1][i] == '1')changex(a, n, m, n-1, i); n--; } int cnt = 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) cnt += a[i][j]=='1'?1:0; if(cnt % 2 == 0)return true; return false; } int main() { // freopen("in", "r", stdin); int t; cin>>t; while(t--){ int n, m; scanf("%d%d ", &n, &m); Board *a = new Board(n, m); int i = 0, j = 0; while(i < n){ a->a[i][j] = getchar(); j++; if(j == m){ getchar();i++;j = 0; } } if(solve(a->a, a->n, a->m))cout<<"Yes"<<endl; else cout<<"No"<<endl; delete a; } return 0; }