Oil Deposits(dfs深搜)

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

解题报告:

这个题是一道深搜的典型题,也是八方搜索,只要八个方向有一个方向满足,就继续递归,遍历下一个符合条件的八个方向。其实深搜的思想也正在于此。

这个题一开始没有想出来的原因是,没有正确的明确理解深搜的意思(orz其实很多人都是在做题中,把这个题的题意了解清楚了,才会真正借用这个题领悟到定义的本质,或者发现自己原来对于某个定义理解是错误的,这样印象就会更深,理解也会更加透彻)。

转到这个题目上面,题意是说@代表油田,*代表空。遇到有@的,如果八个方向,上下左右斜线都有油田那么他们就算一个,否则算多个,最后是输出有多少种油田的数目。

好了,下面是具体步骤分析:要从dfs函数外面就进行判断,如果是@才可以dfs,否则假如说在dfs里面才进行判断,那么如果当前是*,进行dfs,它的八个方向中有一个是@,这样也会继续搜索,和题意不符,所以必须要在外面就进行判断。而且假如被访问过,就要把它设为*,等价于vis=1,这样接下来就不会被继续访问了。

具体思路图示如下(一定要注意顺序问题,即深搜的递归情况,一直往下搜)

Oil Deposits(dfs深搜)_第1张图片

有一个地方的bug,提交了8次才过,还是字符串的问题(此时好想说日了狗啊。。真的改的多艰难)知道为什么吗?还是因为字符串基础打得不牢固,二维数组scanf(”%s“,mp[1])默认是从mp[1][0]开始的,但是我是从[1][1]开始定义的啊啊啊啊啊啊!!!(此时内心悲愤之情难以言喻,恩,还是自己c语言数组基础没有打好,怪自己,欠打啊。。此时声泪俱下。不过也不能用%c啊,那个不好处理空格回车的,也容易错的。真的好多事情都是自己作死的。。),所以要for(i=1;i<=n;i++)scanf("%s",mp[i]+1),一定不要忘了+1啊啊啊啊!!!

恩,到了上自己代码的时候了。。此时我是饱含泪水的,明天一天不想说话好么。。

#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;

#define N 100+10   //不要开太大,比如10000就不行,因为是平方,会更大,开的大了会MLE
int m,n,vis[N][N],ans;
char mp[N][N];
int a[8]={-1,-1,0,1,1,1,0,-1};
int b[8]={0,1,1,1,0,-1,-1,-1};

void dfs(int x,int y)
{
	int nx,ny;
	vis[x][y]=1;

	for(int i=0;i<8;i++)
	{
		nx=x+a[i];
		ny=y+b[i];
		if(nx>0&&nx<=m&&ny>0&&ny<=n&&vis[nx][ny]==0&&mp[nx][ny]=='@')
		{
			dfs(nx,ny);
			mp[x][y]='*';//这个点遍历过了就要设为*,以后不会再遍历到了
		}
	}
}
int main()
{
	while(scanf("%d%d",&m,&n)!=EOF)
	{
		if(m==0&&n==0)
		break;
		memset(mp,0,sizeof(mp));
		memset(vis,0,sizeof(vis));
		ans=0;
		for(int i=1;i<=m;i++)
		{
		    scanf("%s",mp[i]+1);  //提交了八次的错误啊!!一定要记住字符串数组的下标,从0开始啊
		}
		for(int x=1;x<=m;x++)
		{
			for(int y=1;y<=n;y++)
			{
				if(mp[x][y]=='@'&&vis[x][y]==0)   //一定要先判断是否是@啊
				{
					dfs(x,y);
					ans++;   //这个不要加在里面,因为是最终多少次
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;

}

恩,上一份5210的代码,学习一下。。

#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>

#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())

using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef long long ll;

const double esp = 1e-5;

#define N 110

int n, m, vis[N][N];
int dx[] = {0, 0, -1, 1, 1, 1, -1, -1};
int dy[] = {1, -1, 0, 0, 1, -1, 1, -1};
char mp[N][N];

void dfs(int x, int y)
{
	vis[x][y] = 1;
	for (int i = 0; i < 8; ++i) {
		int nx = x + dx[i];
		int ny = y + dy[i];
		if (mp[nx][ny] == '@' && !vis[nx][ny]) {
			dfs(nx, ny);
		}
	}
}

int main(int argc, char *argv[])
{
	while (scanf("%d%d", &n, &m) != EOF) {
		if (n == 0 && m == 0) {
			break;
		}
		clr(mp, 0);
		for (int i = 1; i <= n; ++i) {
			scanf("%s", mp[i] + 1);
		}
		clr(vis, 0);
		int ans = 0;
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				if (!vis[i][j] && mp[i][j] == '@') {
					dfs(i, j);
					++ans;
				}
			}
		}
		printf("%d\n", ans);
	}

	return 0;
}


   
   
   
   

你可能感兴趣的:(HDU,DFS)