机试算法讲解: 第45题 深度优先搜索之寻找沙特石油存储区

/*
问题:在n*m的图中,确定有几个@块,块符合以下条件:其中任意对@块均直接或间接相通,两个@直接相邻或者对角相邻即被视为连通
输入:m(行号) n(列号),m=0标志输入结束,1<=m,n<=100,接下来是m行每行中有n个字符。每个字符对应一块土地,*代表没有石油,@代表有石油
输出:对于每个格子,输出有多少个石油存储区。2个不同的石油处垂直,水平,对角线属于同一个石油存储区。石油存储区<=100

思路:对图上所有位置设置标记位,该标记仅对@有效,按从左到右,从上到下顺序遍历地图上所有位置,如果遍历到@,且未被标记,则所有与其直接相邻或间接相邻的@点与其一起
     组成一个块,将该块中所有的@位置标记为已经计算。
关键:
1 按行输入,maze[i] + 1,scanf("%s",maze[i]+1);//不能加上\n,且maze[i]后面需要加上1
2 凡是用栈均是深度优先
3 薄弱:二维指针
4 在设置剪枝标记时与递归过程分开,在递归的主调函数中要进行过滤,每递归结束1次,进行一次累加
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 101
bool mark[N][N];//剪枝标记
char maze[N][N];//迷宫坐标,存储元素
int goNext[][2] = 
{-1,1,
0,1,
1,1,
-1,0,
1,0,
-1,-1,
0,-1,
1,-1
};//8个位置的下一个走法

//n:行号,m:列号,x:横坐标,y:纵坐标
void DFS(int x,int y,int n,int m)
{
	//判定8个位置的下一个走法
	int iXNext,iYNext;
	for(int i = 0; i < 8 ; i++)
	{
		iXNext = x + goNext[i][0];
		iYNext = y + goNext[i][1];

		//如果已经标记或者超出范围或者为*均跳过
		if(true==mark[iXNext][iYNext] || '*'==maze[iXNext][iYNext] || (iXNext < 0 || iXNext > n || iYNext < 0 || iYNext >m))
		{
			continue;
		}
		else
		{
			//如果没有则递归调用,调用之前先设置标记为真
			mark[iXNext][iYNext] = true;
			DFS(iXNext,iYNext,n,m);
		}
	}
}



int main(int argc,char* argv[])
{
	int n,m;
	int i,j;
	while(EOF!=scanf("%d %d",&n,&m))
	{
		if(n < 1 || n > 100 || m < 1 || m > 100)
		{
			break;
		}

		//接受输入信息
		for(i = 1 ; i <=n ; i++)
		{
			//按行输入?
			scanf("%s",maze[i]+1);//不能加上\n
		}

		//初始化剪枝标记
		for(i = 1 ; i <= n ; i++)
		{
			for(j = 1 ; j <= m ; j++)
			{
				mark[i][j] = false;
			}
		}

		//开始进行递归遍历,设置限定条件
		int iCnt = 0;//设定石油存储区计数器初始化为0
		for(i = 1 ; i <= n ; i++)
		{
			for(j = 1; j <= m ; j++)
			{
				if(true==mark[i][j] || '*'==maze[i][j])
				{
					continue;
				}
				else
				{
					DFS(i,j,n,m);
					iCnt++;
				}
			}
		}
		printf("%d\n",iCnt);
	}
	system("pause");
	getchar();
	return 0;
}

你可能感兴趣的:(DFS,深度优先搜索,机试算法)