poj3279(枚举)

题目链接:https://vjudge.net/contest/294982#problem/C

题意:给定由0,1组成的m*n型矩阵,每次翻转一个结点会顺带翻转与其相邻的结点,问将矩阵翻转为全0的最小步骤,若有多解,输出字典序最小的(将矩阵看成字符串)。

思路:刚开始用搜索一个结点一个结点地搜,老段错误。后来在网上查了后发现这题好象不是搜索题,首先要知道每个结点最多翻一次,因为翻2次和0次一样,3次和1次一样。因为第一行总共有1<<n种翻法,而只要第一行的翻法确定了之后,后面的翻法也就确定了,后面的翻法为若上一个结点为1,则翻转,这样可将前m-1行全部翻成0,最后只用判断最后一行是否全为0,如果是则这种翻法可行。如果我们在第一行的翻法从0到1<<n-1依次枚举,即按字典序枚举,然后只需要找翻转次数最少的,即可得到结果。

AC代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 const int inf=0x3f3f3f3f;
 6 int m,n,Min,cnt,a[20][20],ans[20][20],b[20][20],c[20][20];
 7 int go[5][2]={0,0,-1,0,0,1,1,0,0,-1};
 8 
 9 void flip(int x,int y){
10     for(int i=0;i<5;++i){
11         int xx=x+go[i][0],yy=y+go[i][1];
12         if(xx>=0&&xx<m&&yy>=0&&yy<n)
13             b[xx][yy]=1-b[xx][yy];
14     }
15 }
16 
17 bool check(){
18     bool ret=true;
19     for(int i=0;i<n;++i)
20         if(b[m-1][i]){
21             ret=false;
22             break;
23         }
24     return ret;
25 }
26 
27 void dfs(int num){
28     if(num==m) return;
29     for(int i=0;i<n;++i)
30         if(b[num-1][i]){
31             ++cnt;
32             flip(num,i);
33             c[num][i]=1;
34         }
35     dfs(num+1);
36 }
37 
38 int main(){
39     scanf("%d%d",&m,&n);
40     for(int i=0;i<m;++i)
41         for(int j=0;j<n;++j)
42             scanf("%d",&a[i][j]);
43     Min=inf;
44     for(int i=0;i<(1<<n);++i){
45         memcpy(b,a,sizeof(a));
46         memset(c,0,sizeof(c));
47         cnt=0;
48         for(int j=0;j<=n-1;++j)
49             if(i&(1<<j)){
50                 ++cnt;
51                 flip(0,n-j-1);
52                 c[0][n-j-1]=1;
53             }
54         dfs(1);
55         if(check()){
56             if(Min>cnt){
57                 Min=cnt;
58                 memcpy(ans,c,sizeof(c));
59             }
60         }
61     }
62     if(Min==inf)
63         printf("IMPOSSIBLE\n");
64     else
65         for(int i=0;i<m;++i){
66             for(int j=0;j<n;++j){
67                 printf("%d",ans[i][j]);
68                 if(j!=n-1) printf(" ");
69             }
70             printf("\n");
71         }
72     return 0;
73 }

 

posted @ 2019-04-18 10:07  Frank__Chen  阅读(169)  评论(0编辑  收藏  举报