思路: 1.枚举第一行 递推剩下的 判断最后一行成不成立 2. (误)高斯消元? 如何判断1最少和字典序最小… (所以这种做法好像不可取)
//By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,m,a[16][16],temp[16][16],vis[16][16],xx[]={0,0,0,1,-1},yy[]={0,1,-1,0,0},ans[16][16],tmp=0x3fffff; bool check(int x,int y){return x<n&&x>=0&&y<m&&y>=0;} int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ scanf("%d",&a[i][j]); } } for(int ii=0;ii<(1<<m);ii++){ int cnt=0; memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ temp[i][j]=a[i][j]; } } for(int j=0;j<m;j++){ if(ii&(1<<j)){ cnt++;vis[0][j]=1; for(int k=0;k<=3;k++){ if(check(xx[k],j+yy[k]))temp[xx[k]][j+yy[k]]=!temp[xx[k]][j+yy[k]]; } } } for(int i=1;i<n;i++){ for(int j=0;j<m;j++){ if(temp[i-1][j]){ vis[i][j]=1;cnt++; for(int l=0;l<=4;l++){ if(check(i+xx[l],j+yy[l])){ temp[i+xx[l]][j+yy[l]]=!temp[i+xx[l]][j+yy[l]]; } } } } } for(int k=0;k<m;k++){ if(temp[n-1][k])break; if(k==m-1&&tmp>cnt){ tmp=cnt; for(int j=0;j<n;j++){ for(int l=0;l<m;l++){ ans[j][l]=vis[j][l]; } } } } } if(tmp>333){printf("IMPOSSIBLE");return 0;} for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ printf("%d ",ans[i][j]); } puts(""); } }