【dfs模板】dfs找联通块分区

题目描述

天文学家Doctor博士发明了一种太空分区方法,在这个方法中,宇宙里亮度相近的区域被划为同一个星区。空间中相邻两区域若亮度差不大于给定整数M,则这两区域属于同一星区。现给你一个空间的三维坐标图,每个坐标整点表示一个区域,其值表示其亮度,而其上、下、左、右、前、后六个区域被认为是与其相邻的。请你计算一下该空间内的星区数量。

输入

第一行三个正整数x、y、z(x、y、z<=50),表示空间的长宽高。
第二行一个整数M。
接下来为一行,x*y*z个0~255的整数,按照空间坐标大小的顺序由小到大依次给出每个区域的亮度。
说明:对于空间两点p1(x1,y1,z1)和p2(x2,y2,z2),p1<p2当且仅当(x1<x2)或者(x1=x2且y1<y2)或者(x1=x2且y1=y2且z1<z2)。

输出

一个整数,空间中的星区数量。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int num[55][55][55];
bool mp[55][55][55];
int d;
int n,m,h;
int dx[]={0,0,-1,1,0,0};
int dy[]={1,-1,0,0,0,0};
int dz[]={0,0,0,0,1,-1};
bool check(int x,int y,int z)
{
    if(x<1||x>n||y<1||y>m||z<1||z>h)
        return 1;
    if(mp[x][y][z])
        return 1;
    return 0;
}
void dfs(int x,int y,int z,int p){
    mp[x][y][z]=true;
    for(int i=0; i<6; ++i){
        int next_x=x+dx[i];
        int next_y=y+dy[i];
        int next_z=z+dz[i];
        if(next_x>=1&&next_x<=n&&next_y>=1&&next_y<=m&&next_z>=1&&next_z<=h&&!mp[next_x][next_y][next_z]&&abs(num[next_x][next_y][next_z]-p)<=d)
        {
            dfs(next_x,next_y,next_z,num[next_x][next_y][next_z]);
        }
    }
}
int main(){
   scanf("%d%d%d%d",&n,&m,&h,&d);
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            for(int k=1;k<=h;++k){
                scanf("%d",&num[i][j][k]);
            }
        }
    }
    int ent=0;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            for(int k=1;k<=h;++k){
                if(!mp[i][j][k]){
                    ent++;
                    dfs(i,j,k,num[i][j][k]);
                }
            }
        }
    }
    printf("%d\n",ent);
    return 0;
}

原文地址:https://www.cnblogs.com/Diliiiii/p/10305774.html

时间: 2024-10-09 10:45:39

【dfs模板】dfs找联通块分区的相关文章

HDU 2952 Counting Sheep (DFS找联通块)

题目链接:请戳这里.   题目大意及思路:读懂题意就好了,就是DFS找联通块. 没什么好说的,见代码吧. #include<cstdio> #include<cstring> #include<algorithm> #define N 100+5 using namespace std; int n,m; char g[N][N]; int dir[4][2]={1,0,0,1,-1,0,0,-1}; void dfs(int x,int y) { for(int i=

【dfs模板】找起点到终点的所有可能路径

题目描述 设有一个N*N(2≤N≤10)方格的迷宫,入口和出口分别在左上角和右上角.迷宫格子中分别放有0和1,0表示可通,1表示不能,迷宫走的规则如下图所示:即从某点开始,有八个方向可走,前进方格中数字为0时表示可通过,为1时表示不可通过,要另找路径. 输入 第一行一个正整数N,表示N*N的迷宫.接下来N行,为一个N*N矩阵. 输出 一行一个正整数,表示路径总数. #include <bits/stdc++.h> #define ll long long using namespace std

hdu1198Farm Irrigation(dfs找联通)

题目链接: 啊哈哈,选我选我 思路是:首先根据图像抽象出联通关系..首先确定每一种图形的联通关系,用01值表示不连通与不连通...然后从第1个图形进行dfs搜索.如果碰到两快田地可以联通的话那么标记..注意处理的过程中你的 搜索顺序要和你的每个图形的连通性的顺序相同..然后就是最后看上下.左右能否匹配...看最后有几个不同的快,这就是答案,感觉跟并查集一样..并查集应该也可以做.. 题目: Farm Irrigation Time Limit: 2000/1000 MS (Java/Others

Educational Codeforces Round 5 - C. The Labyrinth (dfs联通块操作)

题目链接:http://codeforces.com/contest/616/problem/C 题意就是 给你一个n行m列的图,让你求’*‘这个元素上下左右相连的连续的’.‘有多少(本身也算一个),每个’*‘的结果取模10.要是为’*‘输出结果,否则输出’.‘. 这个题目就是让你求连续的'.'联通块元素个数,求完一个联通块就把这个联通块标个记号(我设了ok[][]二维数组 表示这个位置的元素的联通块的标号,相连的则为同一个标号),之后这个联通块的每个元素的ans都为f(f为联通块元素个数),然

Codeforces Round #369 (Div. 2) D. Directed Roads dfs求某个联通块的在环上的点的数量

D. Directed Roads ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it consists of n towns numbered from 1to n. There are n directed roads in the Udayland. i-th of them goes from town i to some other town 

分别利用并查集,DFS和BFS方法求联通块的数量

联通块是指给定n个点,输入a,b(1<=a,b<=n),然后将a,b连接,凡是连接在一起的所有数就是一个联通块: 题意:第一行输入n,m,分别表示有n个数,有输入m对连接点,以下将要输入m行(输入数据到文件截止): 输出:第一行要求输出联通块的个数,并在第二行分别输出每个联通块中点的数量,每个数之间以一个空格隔开. 样例 15 31 42 53 5输出:2 2 3样列2 9 81 22 33 43 74 54 67 87 9输出: 19 如果不明白的话可以画图试试,最多花半个小时,要是早这样不

利用DFS求联通块个数

/*572 - Oil Deposits ---DFS求联通块个数:从每个@出发遍历它周围的@.每次访问一个格子就给它一个联通编号,在访问之前,先检查他是否 ---已有编号,从而避免了一个格子重复访问多次 --*/ #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<string.h> #include<algorithm> using namespace std; const int maxn =

【紫书】Oil Deposits UVA - 572 dfs求联通块

题意:给你一个地图,求联通块的数量. 题解: for(所有还未标记的'@'点) 边dfs边在vis数组标记id,直到不能继续dfs. 输出id及可: ac代码: #define _CRT_SECURE_NO_WARNINGS #include "stdio.h" #include<stdio.h> #include<algorithm> #include<string> #include<vector> #include<list&

HDU 4738 Caocao&#39;s Bridges ——(找桥,求联通块)

题意:给你一个无向图,给你一个炸弹去炸掉一条边,使得整个图不再联通,你需要派人去安置炸弹,且派去的人至少要比这条边上的人多.问至少要派去多少个,如果没法完成,就输出-1. 分析:如果这个图是已经是多个联通块了,那么一个人都不用去,如果不是,那么只要找出这个无向图上的桥并且哨兵数量最少的那座把它炸了就行(输出这条边上的哨兵数量即可).直接tarjan就可以写. 注意点:1.可能有重边,所以用手写邻接表的方式存图:2.如果一座桥上没有哨兵,那么你也得至少派去一个人去安置炸弹(因为炸弹不会自己飞过去啊