题目链接:http://poj.org/problem?id=3279
二进制枚举第一行需要翻转的位置,推出剩余行的翻转情况,若最后一行不需翻转则更新答案,否则此方案失败继续枚举下一种。
1 #include<cstdio>
2 #include<cstring>
3 const int maxn=18;
4 int g[maxn][maxn],op[maxn][maxn],temp[maxn][maxn];
5 int n,m;
6 int tp;
7 int dis[5][2]={0,0,0,1,0,-1,1,0,-1,0};
8
9 int need(int r,int l) //判断(r+1,l)是否需要翻转
10 {
11 int ct=g[r][l];
12 for(int i=0;i<5;i++)
13 {
14 int dx=r+dis[i][0];
15 int dy=l+dis[i][1];
16 if(dx>=0&&dx<n&&dy>=0&&dy<m&&temp[dx][dy])
17 ct++;
18 }
19 return ct%2;
20
21 }
22 void flip()
23 {
24 for(int i=1;i<n;i++)
25 for(int j=0;j<m;j++)
26 if(need(i-1,j)) temp[i][j]=1;
27
28 for(int i=0;i<m;i++) //如果最后一行还需翻转,则此方案失败
29 if(need(n-1,i))
30 {
31 tp=0;
32 return;
33 }
34 for(int i=0;i<n;i++)
35 for(int j=0;j<m;j++)
36 if(temp[i][j]) tp++;
37 }
38 int main()
39 {
40 while(scanf("%d%d",&n,&m)!=EOF)
41 {
42 int ans=1e9;
43 for(int i=0;i<n;i++)
44 for(int j=0;j<m;j++)
45 scanf("%d",&g[i][j]);
46 for(int i=0;i<(1<<m);i++) //二进制枚举第0行的状态
47 {
48 memset(temp,0,sizeof(temp));
49 tp=0;
50 for(int j=0;j<m;j++)
51 temp[0][j]=(i>>j)&1;
52 flip();
53 if(ans>tp&&tp>0) //更新答案
54 {
55 ans=tp;
56 memcpy(op,temp,sizeof(temp));
57 }
58 }
59 if(ans==1e9) puts("IMPOSSIBLE");
60 else
61 for(int i=0;i<n;i++)
62 for(int j=0;j<m;j++)
63 printf("%d%c",op[i][j],j==m-1?'
':' ');
64 }
65
66 }