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是自己定的话,那么就可以写成递归,原理一样。