51nod 1851 俄罗斯方块(思维题)

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

 

posted @ 2019-03-27 21:02  7391_KID  阅读(257)  评论(0编辑  收藏  举报