• 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
    ");
    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("
    ");
    71         }
    72     return 0;
    73 }
  • 相关阅读:
    青浦图书志
    师徒俩就这样比划着 讲着该怎么去使用Reactor Programming
    Stephane Maldini and Violeta Georgieva at SpringOne Platform 2019
    reactor 大会
    这样使用Mono.zip就可以合并多个值进行下一步运算
    You are totally right 和 You are absolutely right 区别
    reacctor 1
    developer.ibm.com
    zip~~~~~~~~~~~
    044 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 06 使用do-while循环实现猜字游戏
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10727905.html
Copyright © 2020-2023  润新知