2018-2-7
这里要使用一种特殊的方法求解。。。
假如说我们的第一行已经确定了翻不翻转的状态,如果是一行两个那么就是00,01,10,11,按照这个对第一行操作过之后,那么第一行的状态只能由第二行决定了,若它i,j不符合条件,相应的第二行的i+1,j就要想办法改变它的状态,因为它只能由第一行来改变了,这样看来,我们只要枚举第一行的状态就可以了。
#include<iostream>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
const int MAX = 15;
bool x[MAX+2][MAX+2],y[MAX+2][MAX+2],f[MAX+2][MAX+2],w[MAX+2][MAX+2];
int m,n,cnt,now;
void flip(int p,int q){
y[p][q]=!y[p][q];
y[p+1][q]=!y[p+1][q];
y[p-1][q]=!y[p-1][q];
y[p][q-1]=!y[p][q-1];
y[p][q+1]=!y[p][q+1];
}
void set(){
for (int i=1;i<=m;i++){
for (int j=1;j<=n;j++){
y[i][j]=x[i][j];
f[i+1][j]=0;
}
}
}
bool res(){
for (int i=1;i<=m-1;i++){
for (int j=1;j<=n;j++){
if (y[i][j]){
// cout<<i<<" "<<j<<endl;
flip(i+1,j);
f[i+1][j]=true;
cnt++;
}
}
}
for (int j=1;j<=n;j++){
if (y[m][j]) return false;
}
return true;
}
void dfs(int step){
if (step==n+1){
cnt=0;
for (int j=1;j<=n;j++){
if (f[1][j]){
flip(1,j);
cnt++;
}
}
if (res()){
if (cnt<now){
for (int i=1;i<=m;i++){
for (int j=1;j<=n;j++){
w[i][j]=f[i][j];
}
}
now=cnt;
}
}
set();
return ;
}
f[1][step]=false;
dfs(step+1);
f[1][step]=true;
dfs(step+1);
}
int main(){
while (cin>>m>>n){
int sum=0;
for (int i=1;i<=m;i++){
for (int j=1;j<=n;j++){
cin>>x[i][j];
if (!x[i][j]) sum++;
}
}
if (sum==m*n){
//不需要我们进行翻转了
for (int i=1;i<=m;i++){
for (int j=1;j<n;j++){
cout<<0<<" ";
}
cout<<0<<endl;
}
continue;
}
now=inf;
set();
dfs(1);
if (now==inf){
cout<<"IMPOSSIBLE"<<endl;
continue;
}
for (int i=1;i<=m;i++){
for (int j=1;j<n;j++){
cout<<w[i][j]<<" ";
}
cout<<w[i][n]<<endl;
}
}
}