zoukankan      html  css  js  c++  java
  • ZOJ

    题目大意:

      给一个n*m的X O构成的格子,对一个点操作可以使与它相连通的所有一样颜色的格子翻转颜色(X—>O或O—>X),问给定的矩阵最少操作多少次可以全部变成一样的颜色。

    思路:

      1.每次操作都将本身所在的连通块与和自己相邻的不同颜色的连通块变成同一种颜色,也就是变成一个连通块了,那么要使n次操作后全部变成一样的颜色,也就是从某点出发到达其余所有点。
      2.因此dfs把连通块缩成点,然后相邻的连通块之间建边,枚举以每个点为根的情况,bfs求出每种情况的深度,取最小的即为答案。

    反思:

      1.hea数组初始赋-1会死循,要赋0。
      2.M要开60,50的话要WA。

    代码:

     1 #include<cstdio>
     2 const int dx[4]={-1,0,0,1},dy[4]={0,-1,1,0},M=60,N=3600;
     3 int cnt,num,b[M][M],d[N],q[N],v[N<<1],hea[N],nex[N<<1];
     4 bool f,a[M][M],c[N][N],vis[N];
     5 char s[M];
     6 
     7 void sd(int x,int y)
     8 {
     9     b[x][y]=cnt;
    10     for (int i=0,u,v;i<4;++i)
    11         if (b[u=x+dx[i]][v=y+dy[i]]==0 && a[u][v]==a[x][y]) sd(u,v);
    12 }
    13 
    14 void add(int x,int y) { v[++num]=y,nex[num]=hea[x],hea[x]=num; }
    15 
    16 int dep(int x)
    17 {
    18     int l=0,r=1,y,i; 
    19     for (vis[q[1]=x]=f,d[x]=0;l^r;)
    20         for (i=hea[x=q[++l]];i;i=nex[i])
    21             if (vis[y=v[i]]^f) vis[q[++r]=y]=f,d[y]=d[x]+1;
    22     return d[q[r]];
    23 }
    24 
    25 int main()
    26 {
    27     int T,n,m,i,j,k,x,y,u,v;
    28     for (scanf("%d",&T);T;--T)
    29     {
    30         scanf("%d%d",&n,&m);
    31         for (i=1;i<=n;++i)
    32             for (scanf("%s",s),j=1;j<=m;++j)
    33                 if (s[j-1]=='O') a[i][j]=1; else a[i][j]=0;
    34         for (i=cnt=num=0;i<n+2;++i) b[i][0]=b[i][m+1]=-1;
    35         for (i=0;i<m+2;++i) b[0][i]=b[n+1][i]=-1;
    36         for (i=1;i<=n;++i)
    37             for (j=1;j<=m;++j) b[i][j]=0;
    38         for (i=1;i<=n;++i)
    39             for (j=1;j<=m;++j)
    40                 if (!b[i][j]) ++cnt,sd(i,j);
    41         for (i=1;i<=cnt;++i)
    42             for (j=1;j<=cnt;++j) c[i][j]=1;
    43         for (i=1;i<=cnt;++i) hea[i]=0;
    44         for (i=1;i<=n;++i)
    45             for (j=1;j<=m;++j)
    46                 for (u=b[i][j],k=2;k<4;++k)
    47                     if (~(v=b[x=i+dx[k]][y=j+dy[k]]) && c[u][v] && u^v)
    48                         add(u,v),add(v,u),c[u][v]=c[v][u]=0;
    49         for (i=1;i<=cnt;++i) vis[i]=f;
    50         for (y=cnt,i=1;i<=cnt;++i)
    51             if (f=!f,(x=dep(i))<y) y=x;
    52         printf("%d
    ",y);
    53     }
    54     return 0;
    55 }
  • 相关阅读:
    Android微信九宫格图片展示控件
    ImageView设置rounded corner
    Android TitleBar推荐
    《Windows核心编程》目录索引
    《Windows内核分析》专题-索引目录
    wchar,char,string,wstring互转
    键盘过滤
    串口过滤
    Vmware中Linux 虚拟机与Windows物理机建立共享文件夹
    遍历某一进程模块
  • 原文地址:https://www.cnblogs.com/HHshy/p/7189562.html
Copyright © 2011-2022 走看看