bzoj1647 / P1985 [USACO07OPEN]翻转棋
其实我们只要枚举第一行的状态,后面的所有状态都是可以唯一确定的。
用二进制枚举灰常方便
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define N 20 6 int n,m,a[N][N],b[N][N],c[N][N],d[N][N],ans=2e9; 7 void draw(int x,int y){ 8 b[x][y]^=1; c[x][y]=1; 9 b[x+1][y]^=1; b[x-1][y]^=1; 10 b[x][y+1]^=1; b[x][y-1]^=1; 11 } 12 void find(int x){ 13 int tot=0; 14 for(int i=1;i<=n;++i) 15 for(int j=1;j<=m;++j) 16 b[i][j]=a[i][j],c[i][j]=0; 17 for(int i=1;i<=m;++i) 18 if(x&(1<<(i-1))) 19 draw(1,i),++tot; 20 for(int i=2;i<=n;++i) 21 for(int j=1;j<=m;++j) 22 if(b[i-1][j]) 23 draw(i,j),++tot; 24 if(tot>=ans) return; 25 for(int i=1;i<=n;++i) 26 for(int j=1;j<=m;++j) 27 if(b[i][j]) return; 28 ans=tot; 29 for(int i=1;i<=n;++i) 30 for(int j=1;j<=m;++j) 31 d[i][j]=c[i][j]; 32 } 33 int main(){ 34 scanf("%d%d",&n,&m); 35 for(int i=1;i<=n;++i) 36 for(int j=1;j<=m;++j) 37 scanf("%d",&a[i][j]); 38 for(int i=0,tt=(1<<m)-1;i<=tt;++i) 39 find(i); 40 if(ans==2e9) printf("IMPOSSIBLE"); 41 else{ 42 for(int i=1;i<=n;++i,printf("\n")) 43 for(int j=1;j<=m;++j) 44 printf("%d ",d[i][j]); 45 }return 0; 46 }