bzoj1647 / P1985 [USACO07OPEN]翻转棋

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 }
View Code

 

posted @ 2018-12-05 13:52  kafuuchino  阅读(237)  评论(0编辑  收藏  举报