B题:
看到还没有人发这种题解,我就来发一下吧,枚举第一行所有情况,因为只有4个位置,那么第一行的所有情况有(1<<n) - 1 种,那么直接枚举,对于下面三行还是一个简单的遍历,只要这个点的上方是1,那么我就对这个点操作一下,依次进行到第四行,最后我遍历一下第四行看看是否全为0,如何全为0则成功。

#include<bits/stdc++.h>
using namespace std;

int mp[6][6],nmp[6][6];
char mps[6][6];

void change(int x,int y){//操作这个点
    mp[x][y] = 1 - mp[x][y];
    mp[x + 1][y] = 1 - mp[x + 1][y];
    mp[x][y + 1] = 1 - mp[x][y + 1];
    mp[x - 1][y] = 1 - mp[x - 1][y];
    mp[x][y - 1] = 1 - mp[x][y - 1];
}

int main()
{
    for(int i = 1;i <= 4;i++)
        for(int j = 1;j <= 4;j++) cin >> mps[i][j];
    for(int i = 1;i <= 4;i++)
        for(int j = 1;j <= 4;j++){
            if(mps[i][j] == '1') mp[i][j] = 1;
                else mp[i][j] = 0;
        }
    memcpy(nmp,mp,sizeof mp);
    for(int i = 0;i < (1 << 4);i++){//枚举(1 << n) - 1种情况
        int flag = 0;
        for(int j = 0;j <= 3;j++){//先对第i种情况的第一行进行操作
            if((i >> j) & 1) change(1,4 - j);
        }
        for(int j = 1;j <= 4;j++){//判断第一行是否为1,是1求对第二行对应位置操作
            if(mp[1][j] == 1) change(2,j);
        }
        for(int j = 1;j <= 4;j++){//同理
            if(mp[2][j] == 1) change(3,j);
        }
        for(int j = 1;j <= 4;j++){//同理
            if(mp[3][j] == 1) change(4,j);
        }
        for(int j = 1;j <= 4;j++){//最后判断最后一行是否合法即可
            if(mp[4][j] == 1){
                flag = 1;
            }
        }
        if(flag == 0) {
            cout << "YES" << endl;
            return 0;
        }
        memcpy(mp,nmp,sizeof nmp);
    }
    cout << "NO" << endl;
    return 0;
}

因为此题的n很小,我直接枚举了,如果n是自己定的话,那么就可以写成递归,原理一样。