题目大意:
给一个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\n",y); 53 } 54 return 0; 55 }
转载于:https://www.cnblogs.com/HHshy/p/7189562.html
相关资源:JAVA上百实例源码以及开源项目