HDU1241:Oil Deposits

点击打开题目链接

Oil Deposits

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


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
 

Source
Mid-Central USA 1997
 

Recommend
Eddy
 


=====================================题目大意=====================================


“*”代表没有油田,“@”代表有油田,相邻(八个方向上)的油田算同一个油田存储地,给出地图求解共有多少个油田存储地。


=====================================算法分析=====================================


简单搜索题,用BFS和DFS做没啥好说的,这里写一下用并查集做的思路:

1、基本思路:将每一个油田作为一个元素,每一个油田存储地作为一个集合,对所有元素使用并查集。

2、并查思路:对于一个元素来说查并所有与其同属一个集合的元素是会造成不必要的重复的。

             比如说元素(1,2)与元素(1,3)同属一个集合,那么对于元素(1,2)会查并到元素(1,3)而对于元素(1,3)又会查

             并到元素(1,2)。

             实际上对于一个元素来说只需查并其左上方,正上方,右上方,正左方(这只是一种方案)四个方向上与其同属一个

             合的元素即可。

             根据这一性质,这里的地图甚至可以使用滚动数组来保存,但是嫌麻烦,没写了。。。

3、解题思路:初始sum为0,每发现一个油田++sum,每将一个油田并入集合--sum,最后sum即答案。


=======================================代码=======================================




#include<stdio.h>
#include<string.h>

#define IDENTIF(DOT) (&DOT-&Map[0][0])                  //点的编号
#define LEGCORD(X,Y) (0<=X&&X<M&&0<=Y&&Y<N)             //合法坐标  

const int MAXS=105;

const int Dir[4][2]={{-1,-1},{-1,0},{-1,1},{0,-1}};     //只需四个方向

int M,N,P[MAXS*MAXS];

char Map[MAXS][MAXS];

int Find(int x)
{
	return P[x]==-1?x:P[x]=Find(P[x]);
}

void Union_Find()
{
	memset(P,-1,sizeof(P));
	int sum=0;
	for(int curi=0;curi<M;++curi)
	{
	    scanf("%*c%s",Map[curi]);
		for(int curj=0;curj<N;++curj) if(Map[curi][curj]=='@')
        {
			++sum;
			for(int n=0;n<4;++n)
			{
				int tmpi=curi+Dir[n][0];
				int tmpj=curj+Dir[n][1];
				if(LEGCORD(tmpi,tmpj)&&Map[tmpi][tmpj]=='@')
				{
					int pcur=Find(IDENTIF(Map[curi][curj]));
					int ptmp=Find(IDENTIF(Map[tmpi][tmpj]));
					if(pcur!=ptmp) { P[ptmp]=pcur;  --sum; }
				}
			}
		}
	}
	printf("%d\n",sum);
}

int main()
{
	while(scanf("%d%d",&M,&N)==2&&M&&N) 
	{
		Union_Find();
	}
	return 0;
}

你可能感兴趣的:(数据结构,搜索,并查集)