n,m<=15,直接搞肯定不行,考虑一行一行来,
每一行的状态只与三行有关,所以从第一行开始枚举,每一次让下面一行填上他上面那行的坑
最后一行必须要同时满足他自己和他上面那行,否则舍去
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> using namespace std; int n,m,a[18][18],now[18][18],tim[18][18],nxt[18],final[18],num,tot; bool bo=0; int getnum(int x){ int ans=0; while(x){ ans+=x&1; x>>=1; } return ans; } void dfs(int step,int x){ num+=getnum(x); for(int i=m-1;i>=0;i--){ if(x&(1<<i)){ now[step][i]^=1; if(i<m-1) now[step][i+1]^=1; if(i>0) now[step][i-1]^=1; if(step<n) now[step+1][i]^=1; } } nxt[step+1]=0; for(int i=m-1;~i;i--) nxt[step+1]|=now[step][i]*(1<<i); if(step==n){ for(int i=m-1;~i;i--) if(now[n][i]) return; if(num>tot) return; bo=1; tot=num; for(int i=1;i<=n;i++) final[i]=nxt[i]; return; } dfs(step+1,nxt[step+1]); } int main() { scanf("%d%d",&n,&m); tot=100000; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); for(int i=(1<<m)-1;~i;i--){ num=0; for(int j=0;j<m;j++) for(int k=1;k<=n;k++) now[k][j]=a[k][m-j]; nxt[1]=i; dfs(1,i); } if(!bo){ printf("IMPOSSIBLE "); return 0; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) printf("%d ",(final[i]>>(m-j))&1); printf(" "); } return 0; }