hdu Farm Irrigation
这题第一感觉是用搜索做,暴力就可以解决,这里将水管转换成一个个3*3的矩阵,然后搜素就可以了。写完之后确实一遍过掉了,31ms。附上代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include"iostream" #include"stdio.h" #include"algorithm" #include"cmath" #include"queue" #include"stack" #include"vector" #include"string" #include"string.h" using namespace std; const int mx=1005; int A[3][3]={{0,1,0},{1,1,0},{0,0,0}}; int B[3][3]={{0,1,0},{0,1,1},{0,0,0}}; int C[3][3]={{0,0,0},{1,1,0},{0,1,0}}; int D[3][3]={{0,0,0},{0,1,1},{0,1,0}}; int E[3][3]={{0,1,0},{0,1,0},{0,1,0}}; int F[3][3]={{0,0,0},{1,1,1},{0,0,0}}; int G[3][3]={{0,1,0},{1,1,1},{0,0,0}}; int H[3][3]={{0,1,0},{1,1,0},{0,1,0}}; int I[3][3]={{0,0,0},{1,1,1},{0,1,0}}; int J[3][3]={{0,1,0},{0,1,1},{0,1,0}}; int K[3][3]={{0,1,0},{1,1,1},{0,1,0}}; int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; int maze[mx][mx]; bool visited[mx][mx]; int m,n,wellspring; bool judge(int x,int y) { if(x>=0&&x<3*m&&y>=0&&y<3*n&&maze[x][y]==1&&!visited[x][y]) return true; return false; } void dfs(int x,int y) { int dx,dy; for(int i=0;i<4;i++) { dx=x+dir[i][0]; dy=y+dir[i][1]; if(judge(dx,dy)) { visited[dx][dy]=true; dfs(dx,dy); } } } void creat_maze(int a[][3],int i,int j) { int p,q; for(p=i*3;p<i*3+3;p++) { for(q=j*3;q<j*3+3;q++) { maze[p][q]=a[p-i*3][q-j*3]; } } } void wellspring_count() { int i,j; for(i=0;i<3*m;i++) { for(j=0;j<3*n;j++) { if(maze[i][j]==1&&!visited[i][j]) { wellspring++; visited[i][j]=true; dfs(i,j); } } } printf("%d\n",wellspring); } void input() { int i,j; while(scanf("%d%d",&m,&n),m!=-1||n!=-1) { memset(visited,false,sizeof(visited)); wellspring=0; char pipe; for(i=0;i<m;i++) { getchar(); for(j=0;j<n;j++) { scanf("%c",&pipe); switch(pipe) { case 'A': creat_maze(A,i,j);break; case 'B': creat_maze(B,i,j);break; case 'C': creat_maze(C,i,j);break; case 'D': creat_maze(D,i,j);break; case 'E': creat_maze(E,i,j);break; case 'F': creat_maze(F,i,j);break; case 'G': creat_maze(G,i,j);break; case 'H': creat_maze(H,i,j);break; case 'I': creat_maze(I,i,j);break; case 'J': creat_maze(J,i,j);break; case 'K': creat_maze(K,i,j);break; } } } wellspring_count(); } } int main() { // freopen("E:\\in.txt","r",stdin); input(); return 0; }
但是这是一个并查集专题里的题,所以应该还会有更高效的方法,毕竟我的代码里没有用到并查集。
所以又想了一下,瞬变看了一下别人的并查集思路,又写了一个代码。然而,这次用并查集却死活过不了。。。找bug找了接近两个小时了,自己找的案例都过掉了。。。
先附上wa掉的代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include"iostream" #include"stdio.h" #include"string" #include"string.h" #include"cmath" #include"algorithm" #include"ctype.h" #include"queue" #include"stack" #include"vector" using namespace std; const int mx=55; int maze[mx][mx]; int fa[mx*mx]; int m,n,wellspring; int dir[4][2]={{0,-1},{-1,0},{0,1},{1,0}};//左上右下 //左上右下有水管接口的用1表示 int farm[11][4]= { {1,1,0,0}, {0,1,1,0}, {1,0,0,1}, {0,0,1,1}, {0,1,0,1}, {1,0,1,0}, {1,1,1,0}, {1,1,0,1}, {1,0,1,1}, {0,1,1,1}, {1,1,1,1} }; void Set() { int i; for(i=0;i<m*n;i++) fa[i]=i; } int Find(int x) { int t1,t2=x; while(t2!=fa[t2]) t2=fa[t2]; return t2; } void Union(int x,int y) { int fx=Find(x); int fy=Find(y); if(fx!=fy) { fa[fx]=fy; wellspring--; } } bool judge(int k,int x,int y) { switch(k) { case 0: if(farm[x][0]&&farm[y][2]) return true; break; case 1: if(farm[x][1]&&farm[y][3]) return true; break; case 2: if(farm[x][2]&&farm[y][0]) return true; break; case 3: if(farm[x][3]&&farm[y][1]) return true; break; } return false; } void Count() { int i,j,k,dx,dy; for(i=0;i<m;i++) { for(j=0;j<n;j++) { for(k=0;k<4;k++) { dx=i+dir[k][0]; dy=j+dir[k][1]; if(dx>=0&&dx<m&&dy>=0&&dy<n)//判定越界条件 if(judge(k,maze[i][j],maze[dx][dy])) Union(i*m+j,dx*m+dy); } } } } void Input() { int i,j; while(scanf("%d%d",&m,&n),m>=1&&n>=1) { Set(); wellspring=m*n; char pipe; for(i=0;i<m;i++) { getchar(); for(j=0;j<n;j++) { scanf("%c",&pipe); maze[i][j]=pipe-'A'; } } Count(); printf("%d\n",wellspring); } } int main() { // freopen("E:\\in.txt","r",stdin); Input(); return 0; }