Num 35 : HDOJ : 1241 Oil Deposits [ 深度优先搜索算法 ] [ 非回溯 ][ 图论 ]

 

  DFS( Depth-First-Search ) 深度优先搜索算法 :


          深度优先搜索算法是图论的基础算法,在介绍DFS之前,我们先来介绍一下什么是深度优先搜索:


    一、DFS概念:


          正如算法名称那样,深度优先搜索所遵循的搜索策略是尽可能“深”地搜索图。

          在深度优先搜索中,对于最新发现的顶点,如果它还有以此为起点而未探测到的边,就沿此边继续汉下去。

         这一过程一直进行到已发现从源结点可达的所有结点为止,整个进程反复进行直到所有结点都被发现为止。


    二、DFS分类:

           对于解决问题的不同,分为:回溯法和非回溯法;


     ①. 非回溯法 : 对于图中的路线,仅搜索一次,之后不再搜索;

           例 : 计算一片土地中满足条件的最大的一片土地;


     ②. 回溯法 :对于图中的路线,不止搜索一次,每次搜索之后,为了下一次路线,都要将图复原;

           例 : 计算最短的行走路线问题;


    三、DFS算法的实现:

            1. 作为图论,首先我们需要定义一个 m x n 的地图 map[ M ][ N ]来存储地图[ 通常为二维空间 ],和 x,y作为坐标;


            2. DFS函数:



  1、非回溯法 :

void fun(int x,int y)
{
    if(x<1||x>m||y<1||y>n) return;
    if(map[x][y]==0) return;
    if(map[x][y]==1)
	 {
	        map[x][y]=0;
 		num++;
		fun(x-1,y);
 		fun(x+1,y);
 		fun(x,y-1);
 		fun(x,y+1);
 	}
}

              ①. 第一个if : 若左边在图像之外,不满足条件,返回;

              ②. 第二个if : 如果碰到不满足条件的点[ 这里用 ‘0’ 表示 ],返回;


              ③. 如果是 ‘1’ [ 满足条件的点 ],将其标记为已经走过的点,并向处该点之外的其他四个方向搜索;



  2、回溯法 :


void fun(int x,int y)
{
    if(x<1||x>m||y<1||y>n) return;
    if(map[x][y]=='0') return;
	map[x][y]='0';
	snum++;
	fun(x-1,y);
	fun(x+1,y);
	fun(x,y-1);
	fun(x,y+1);
	snum--;
	map[x][y]='1';
}

             ①. 前面都是一样的;


              ②. 只需要在函数后,加 map[ x ][ y ]=' 1 ' , 即可;



例题:

Oil Deposits

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 18604    Accepted Submission(s): 10719


Problem Description
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 analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.
 

Input
The input file contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket.
 

Output
For each grid, output the number of distinct oil deposits. Two different pockets are part of the same oil deposit if they are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.
 

Sample Input
  
  
1 1 * 3 5 *@*@* **@** *@*@* 1 8 @@****@* 5 5 ****@ *@@*@ *@**@ @@@*@ @@**@ 0 0
 

Sample Output
  
  
0 1 2 2

            @代表油田,相临的@一共算一大片油田,问总共有多少片油田;


     题目分析:

            1. 从左上角开始搜索,将某一片能搜索的油田都赋予 ‘* ’ ,并且数量加一;

            2. 一直搜索到地图结束( 右下角 );


AC代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
char map[110][110];
int m,n,count;
void fun(int x,int y)
{
    if(x<1||x>m||y<1||y>n) return;
    if(map[x][y]=='*') return;
    map[x][y]='*';
    fun(x-1,y);
    fun(x+1,y);
    fun(x,y+1);
    fun(x,y-1);
    fun(x+1,y+1);
    fun(x-1,y+1);
    fun(x-1,y-1);
    fun(x+1,y-1);
}
int main()
{
	while(scanf("%d%d",&m,&n),m|n)
	{
		count=0;
		int i,j;
		for(i=1;	i<=m;	i++)
			for(j=1;	j<=n;	j++)
				scanf(" %c",&map[i][j]);
		while(1)
		{
			for(i=1;	i<=m;	i++)
				for(j=1;	j<=n;	j++)
					if(map[i][j]=='@')
					{
						fun(i,j);
						count++;
					}
			if(i==m+1&&j==n+1) break;
		}
		printf("%d\n",count);
	}
    return 0;
}


            在做DFS的时候要注意,许多变量要定义为全局变量,否则无法存储结果;




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值