分析:假设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", &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; }