题目大意
给定一个N*M的网格,每个网格里有一个数字,0或者1,要求你翻转尽量少的网格,使得所有网格的数字都变为0,对于某一个网格进行翻转操作时,与它有公共边的网格全部会被翻转。
题解
和Uva11464的方法一样,都是枚举第一行的状态,只要第一行的状态确定了,那么每行的状态都确定了。
代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MAXN 20 int a[MAXN][MAXN],b[MAXN][MAXN],ans[MAXN][MAXN]; int n,m; int check(int s) { int i,j; for(i=0; i<m; i++) if(s&(1<<i)) { ans[0][i]=1; b[0][i]^=1; if(1<n) b[1][i]^=1; if(i-1>=0) b[0][i-1]^=1; if(i+1<m) b[0][i+1]^=1; } for(i=1; i<n; i++) for(j=0; j<m; j++) if(b[i-1][j]) { ans[i][j]=1; b[i][j]^=1; b[i-1][j]^=1; if(i+1<n) b[i+1][j]^=1; if(j-1>=0)b[i][j-1]^=1; if(j+1<m) b[i][j+1]^=1; } for(i=0;i<m;i++) if(b[n-1][i]) return 0; return 1; } void print() { int i,j; for(i=0; i<n; i++) { for(j=0; j<m-1; j++) printf("%d ",ans[i][j]); printf("%d\n",ans[i][j]); } } int main(void) { int i,j,flag; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0; i<n; i++) for(j=0; j<m; j++) scanf("%d",&a[i][j]); flag=0; for(i=0; i<(1<<m); i++) { memcpy(b,a,sizeof(a)); memset(ans,0,sizeof(ans)); if(check(i)) { flag=1; print(); break; } } if(!flag) printf("IMPOSSIBLE\n"); } return 0; }