nyoj27-水池数目 (求连通块数目)【dfs】

http://acm.nyist.net/JudgeOnline/problem.php?pid=27

水池数目

时间限制:3000 ms  |  内存限制:65535 KB

难度:4

描述
南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上仅标识了此处是否是水池,现在,你的任务来了,请用计算机算出该地图中共有几个水池。
输入
第一行输入一个整数N,表示共有N组测试数据
每一组数据都是先输入该地图的行数m(0<m<100)与列数n(0<n<100),然后,输入接下来的m行每行输入n个数,表示此处有水还是没水(1表示此处是水池,0表示此处是地面)
输出
输出该地图中水池的个数。
要注意,每个水池的旁边(上下左右四个位置)如果还是水池的话的话,它们可以看做是同一个水池。
样例输入
2
3 4
1 0 0 0
0 0 1 1
1 1 1 0
5 5
1 1 1 1 0
0 0 1 0 1
0 0 0 0 0
1 1 1 0 0
0 0 1 1 1
样例输出
2
3

题意:就是求这个二维地图上由1组成的连通块的数目。

题解1:dfs

 1 #include <fstream>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5
 6 using namespace std;
 7
 8 const int N=100;
 9 int m,n,ans;
10 int a[N][N];
11 bool b[N][N];
12 int xy[2][4]={{1,-1,0,0},{0,0,1,-1}};
13
14 bool check(int x,int y);
15 void dfs(int x,int y);
16
17 int main()
18 {
19     //freopen("D:\\input.in","r",stdin);
20     //freopen("D:\\output.out","w",stdout);
21     int T;
22     scanf("%d",&T);
23     while(T--){
24         ans=0;
25         scanf("%d%d",&m,&n);
26         for(int i=0;i<m;i++)
27             for(int j=0;j<n;j++)
28                 scanf("%d",&a[i][j]);
29         memset(b,0,sizeof(b));
30         for(int i=0;i<m;i++)
31             for(int j=0;j<n;j++)
32                 if((!b[i][j])&&a[i][j])    dfs(i,j),ans++;
33         printf("%d\n",ans);
34     }
35     return 0;
36 }
37 bool check(int x,int y){
38     return x>=0&&x<m&&y>=0&&y<n&&b[x][y]==0;
39 }
40 void dfs(int x,int y){
41     b[x][y]=1;
42     if(!a[x][y])    return;
43     int tx,ty;
44     for(int i=0;i<4;i++){
45         tx=x+xy[0][i];
46         ty=y+xy[1][i];
47         if(check(tx,ty))  dfs(tx,ty);
48     }
49 }

题解2:非递归方式:队列。建立队列q,遍历二维图所有点,对每个点扩展的点存入队列,再一一处理。

 1 #include <stdio.h>
 2
 3 int main()
 4 {
 5     int t,n,m,e=1000,i,j,k,s,num,q[10010],r[110][110];
 6     scanf("%d",&t);
 7     while(t--)
 8     {
 9         scanf("%d%d",&n,&m);
10         for(i=0;i<n;i++)
11             for(j=0;j<m;j++)
12                 scanf("%d",&r[i][j]);
13         num=0;
14         for(i=0;i<n;i++)
15             for(j=0;j<m;j++)
16             {
17                 if(r[i][j]==1)
18                 {
19                     int a,b;
20                     a=i;
21                     b=j;
22                     k=1;
23                     s=0;
24                     while(s<k)
25                     {
26                         if(r[a][b-1]==1)
27                         {
28                             q[k++]=a*e+b-1;
29                             r[a][b-1]=0;
30                         }
31                         if(r[a][b+1]==1)
32                         {
33                             q[k++]=a*e+b+1;
34                             r[a][b+1]=0;
35                         }
36                         if(r[a-1][b]==1)
37                         {
38                             q[k++]=(a-1)*e+b;
39                             r[a-1][b]=0;
40                         }
41                         if(r[a+1][b]==1)
42                         {
43                             q[k++]=(a+1)*e+b;
44                             r[a+1][b]=0;
45                         }
46                         a=q[++s]/e;
47                         b=q[s]%e;
48                     }
49                     num++;
50                 }
51             }
52         printf("%d\n",num);
53     }
54     return 0;
55 }
时间: 2024-08-10 14:21:22

nyoj27-水池数目 (求连通块数目)【dfs】的相关文章

UVA 572 dfs求连通块

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyze

UVA 572 Oil Deposits油田(DFS求连通块)

UVA 572     DFS(floodfill)  用DFS求连通块 Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M

DFS入门之二---DFS求连通块

用DFS求连通块也是比较典型的问题, 求多维数组连通块的过程也称为--“种子填充”. 我们给每次遍历过的连通块加上编号, 这样就可以避免一个格子访问多次.比较典型的问题是”八连块问题“.即任意两格子所在位置相邻(上下左右对角共八个方位),则在一个连通块.典型例题:HDU 1241 Oil Deposits 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1241 题目描述:输入m行n列的字符矩阵, 统计字符“@”组成八连块的个数. 题意分析:读入数据

UVA 572 -- Oil Deposits(DFS求连通块+种子填充算法)

UVA 572 -- Oil Deposits(DFS求连通块) 图也有DFS和BFS遍历,由于DFS更好写,所以一般用DFS寻找连通块. 下述代码用一个二重循环来找到当前格子的相邻8个格子,也可用常量数组或者写8条DFS调用. 下述算法是:种子填充(floodfill) 两种连通区域 四连通区域:从区域内一点出发,可通过上.下.左.右四个方向的移动组合,在不越出区域的前提下,能到达区域内的任意像素 八连通区域:从区域内每一像素出发,可通过八个方向,即上.下.左.右.左上.右上.左下.右下移动的

油田(Oil Deposits)-用DFS求连通块

[本博文非博主原创,均摘自:刘汝佳<算法竞赛入门经典>(第2版) 6.4 图] [程序代码根据书中思路,非独立实现] 例题6-12 油田(Oil Deposits,UVa572) 输入一个m行n列的字符矩阵,统计字符"@"组成多少个八连块.如果两个字符"@"所在的格子相邻(横.纵或者对角线方向),就说它们属于一个八连块.例如,下图中有两个八连块. 一.分析 1.1 整体思路 图也有DFS和BFS遍历.由于DFS更容易编写,一般用DFS查找连通块:从每个&

P1197 [JSOI2008]星球大战 [删边求连通块个数]

展开 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武器.凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球.由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来. 现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽

zoj3080 ChiBi --- floyd求连通块内最短路

此题最大最小搞的太复杂...并查集维护连通块,连通块内floyd就可以了 #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #

Codeforces 278C Learning Languages(并查集) 求连通块

Codeforces 278C Learning Languages(并查集) 求连通块 为什么最后还要getfather 一遍 比如 x 是 y 的父亲 然后你 Union(x,z) 然后 z 变成了 x 父亲 然后 y 的祖先就是错的了 题解 求一个无向图中有几个连通块 sum 特判 一下 如果 每一个人的语言都为 0 则答案为 sum 其他 答案则为 sum - 1 1 #include <bits/stdc++.h> 2 using namespace std ; 3 4 const

C. Edgy Trees Codeforces Round #548 (Div. 2) 并查集求连通块

C. Edgy Trees time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a tree (a connected undirected graph without cycles) of nn vertices. Each of the n−1n−1 edges of the tree is col