【题意】一个m*n的01矩阵,每次点击(x,y),那么她的上下左右以及本身就会0变1,1变0,问把矩阵变成全0的,最小需要点击多少步。

【分析】只需要枚举第一行的状态即可,后面的状态都可以根据第一行直接推出来,还要注意这题还有不存在的情况,详见代码!

【AC代码】

#include <map>
#include <set>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,m;
int maze[15][15];
int ans[15][15];
int b[15][15];
void press(int x,int y){
    ans[x][y] = 1;
    b[x][y] = 1-b[x][y];
    if(x>0)   b[x-1][y] = 1-b[x-1][y];
    if(x<n-1) b[x+1][y] = 1-b[x+1][y];
    if(y>0)   b[x][y-1] = 1-b[x][y-1];
    if(y<m-1) b[x][y+1] = 1-b[x][y+1];
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                scanf("%d",&maze[i][j]);
            }
        }
        bool flag=false;
        for(int s=0; s<(1<<m); s++){
            memset(ans,0,sizeof(ans));
            for(int i=0; i<n; i++){
                for(int j=0; j<m; j++){
                    b[i][j] = maze[i][j];
                }
            }
            for(int i=0; i<m; i++){
                if(s&(1<<i)) press(0,i);
            }
            for(int i=1; i<n; i++){
                for(int j=0; j<m; j++){
                    if(b[i-1][j]==1) press(i,j);
                }
            }
            bool *** = true;
            for(int i=0; i<m; i++){
                if(b[n-1][i]==1) *** = false;
            }
            if(***){
                flag = true;
                for(int i=0; i<n; i++){
                    for(int j=0; j<m-1; j++){
                        printf("%d ",ans[i][j]);
                    }
                    printf("%d\n",ans[i][m-1]);
                }
                break;
            }
        }
        if(flag==false)
            puts("IMPOSSIBLE");
    }
    return 0;
}