0 0 0 0
//参考《挑战程序设计》一书,对该题的分析,解法
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<algorithm>
#define bug printf("-----\n");
using namespace std;
const int maxn=20;
const int inf=210000;
typedef long long ll;
int m,n;
int opt[maxn][maxn];
int a[maxn][maxn];
int tmp[maxn][maxn];
int dx[]= {0,0,1,-1,0};
int dy[]= {-1,1,0,0,0};
int getcolor(int x,int y)
{
    int ans=a[x][y];
    for(int i=0; i<5; i++)
    {
        int xx=x+dx[i];
        int yy=y+dy[i];
        if(xx>=0&&xx<m&&yy>=0&&yy<n)
            ans+=tmp[xx][yy];
    }
    return ans%2;
}
int cal()
{
    int i,j;
    for(i=1; i<m; i++)
        for(j=0; j<n; j++)
            if(getcolor(i-1,j))
                tmp[i][j]=1;
    for(i=0;i<n;i++)
        if(getcolor(m-1,i))return -1;
    int ans=0;
    for(i=0;i<m;i++)
        for(j=0;j<n;j++)
        ans+=tmp[i][j];
    return ans;
}
void solve()
{
    int rec=-1;
    int i,j;
    for(i=0;i<1<<n;i++)
    {
        memset(tmp,0,sizeof(tmp));
        for(j=0;j<n;j++)
        {
            tmp[0][n-j-1]=i>>j&1;
        }
        int num=cal();
        if(num>=0&&(rec>num||rec<0))
        {
            rec=num;
            memcpy(opt,tmp,sizeof(tmp));
        }
    }
    if(rec<0)
        printf("IMPOSSIBLE\n");
    else
    {
        for(i=0;i<m;i++)
        {
            for(j=0;j<n;j++)
            printf("%d%c",opt[i][j],j==n?'\n':' ');
            printf("\n");
        }
    }
}
int main()
{
    int  i,j,t,k;
    while(~scanf("%d%d",&m,&n))
    {
        for(i=0; i<m; i++)
            for(j=0; j<n; j++)
                cin>>a[i][j];
        solve();
    }
    return 0;
}
D - Fliptile POJ3279 搜索(反转开关经典问题,二进制表示集合)
原文:http://blog.csdn.net/u013167299/article/details/44464869