【DFS&BFS】HDU1241-Oil Deposits
2016-07-30 09:59
435 查看
【这里不用看】这是一道神奇的题,它之所以神奇不是因为它有多实用,也不是因为它有多难,而是因为它可以用两种方法解出来:一种是深搜(DFS),另一种是广搜(BFS)。所以学长连着两天把这道题叫我们用这两种方法练习,结果第二天还真的有个boy上去就用了第一天的方法把代码bia上去然后显示两分钟就完成了,感觉很厉害的样子呢~(不是我不是我不是我)
【题目】
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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
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.
[align=left]Sample Input[/align]
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
[align=left]Sample Output[/align]
0
1
2
2
[align=left]Source[/align]
Mid-Central USA 1997
【题意】
自从进协会我已经很久没看到中文题了TAT,渣渣英语谁来救救我!
说是第一行输入行列数(输入行数为0时结束),下面紧跟着的几行几列由*和@组成,要求输出一个数字,表示有几组连着的@。
注意这里面相邻斜着的@也算是连着的!
【思路】
先说深搜吧,深搜的原理就是顺着一条路直接找到头再拐回来找其他的路,对于这道题来讲,它拐回来时是不需要再把标记重置的,踩过一遍之后草就死了,所以当我们找到一个@并开始找跟它连在一起的@以后,直接把连在一起的@标记已访问,回去时访问不重置,那么跟这个@连着的这一片@就都不用再检查了,下次再进入函数,就是从另外的没遍历过的@开始找。这样的话,我们从main函数里传递给dfs函数几个@的坐标,就有几个连在一起的@群了。
至于广搜,原理跟深搜是一样的,但是广搜用了15ms,深搜用了46ms,更省了点时间。广搜需要用到队列,而坐标是二维的,这就要求推入队列时要把储存着坐标位置信息的结构推进去,要建立结构体,推入队列的都是将要被检查的元素,当队列非空时取出元素依次检查。
【代码】
DFS:
BFS:
唯一两种方法都一次过掉的题,虽然不难但是总要写个博客纪念一下~~~!
【题目】
Oil Deposits
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
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.
[align=left]Sample Input[/align]
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
[align=left]Sample Output[/align]
0
1
2
2
[align=left]Source[/align]
Mid-Central USA 1997
【题意】
自从进协会我已经很久没看到中文题了TAT,渣渣英语谁来救救我!
说是第一行输入行列数(输入行数为0时结束),下面紧跟着的几行几列由*和@组成,要求输出一个数字,表示有几组连着的@。
注意这里面相邻斜着的@也算是连着的!
【思路】
先说深搜吧,深搜的原理就是顺着一条路直接找到头再拐回来找其他的路,对于这道题来讲,它拐回来时是不需要再把标记重置的,踩过一遍之后草就死了,所以当我们找到一个@并开始找跟它连在一起的@以后,直接把连在一起的@标记已访问,回去时访问不重置,那么跟这个@连着的这一片@就都不用再检查了,下次再进入函数,就是从另外的没遍历过的@开始找。这样的话,我们从main函数里传递给dfs函数几个@的坐标,就有几个连在一起的@群了。
至于广搜,原理跟深搜是一样的,但是广搜用了15ms,深搜用了46ms,更省了点时间。广搜需要用到队列,而坐标是二维的,这就要求推入队列时要把储存着坐标位置信息的结构推进去,要建立结构体,推入队列的都是将要被检查的元素,当队列非空时取出元素依次检查。
【代码】
DFS:
<pre name="code" class="cpp">#include<cstdio> #include<string.h> #define N 101 using namespace std; int dir[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,1},{1,-1},{-1,-1}};//由于斜着也算连着,所以设置8个方向 int mark ,b ,m,n,ans;//mark[][]用来检查该位置元素是否被遍历,是为1,否为0;至于b[][]额……只是一个迷の数组; char a ; int dfs(int x,int y); int main() { while(scanf("%d%d",&m,&n)&&m) { ans=0; memset(b,0,sizeof(b)); memset(mark,0,sizeof(mark));//输入数据可能有多组,所以每次计算之前都要重置mark每一项都为0,表示都还没有遍历,ans也要重置为0; for(int i=0;i<m;i++)//输入地图数据 { for(int j=0;j<n;j++) { char aa; o:scanf("%c",&aa); if(aa=='\n'||aa=='\0') goto o; else if(aa=='@') b[i][j]=1; a[i][j]=aa; } } for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(b[i][j]==1&&mark[i][j]==0)//如果@没有遍历,就让答案ans+1, { ans++; dfs(i,j);//实际上dfs函数在这里的作用就是把跟被检查的@连在一起的@全部标记为已遍历。 } } } printf("%d\n",ans); } } int dfs(int x,int y) { mark[x][y]=1;//标记此坐标为已遍历 for(int i=0;i<8;i++) { int nx=x+dir[i][0];//nx、ny为以原始x,y值为基础向8个方向走一步时新坐标的数值 int ny=y+dir[i][1]; if(nx>=0&&ny>=0&&nx<m&&ny<n&&!mark[nx][ny]&&a[nx][ny]!='*')//检查新坐标是否越界、是否已被遍历,是不是@符号 { dfs(nx,ny);//符合条件的话标记此坐标 } } }
BFS:
<pre name="code" class="cpp">#include<cstdio> #include<string.h> #include<queue>//BFS需要队列来辅助 using namespace std; int m,n,ans,vis[101][101],dir[8][2]={1,0,-1,0,0,1,0,-1,1,-1,1,1,-1,-1,-1,1}; char a[101][101]; struct inf{ int x,y; }xy;//结构,用来做压缩包把坐标合二为一 queue <inf> q; void bfs(void); int main() { while(~scanf("%d%d",&m,&n)&&m) { while(!q.empty()) q.pop();//重置队列 memset(vis,0,sizeof(vis));//重置访问标记 ans=0; getchar(); for(int i=0;i<m;i++)//输入数据 { scanf("%s",&a[i]); } for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(a[i][j]=='@'&&vis[i][j]==0)//此处原理同DFS { xy.x=i;xy.y=j;//压缩坐标 q.push(xy);//入队 bfs();//进入bfs进行标记 ans++; } } } printf("%d\n",ans); } } void bfs(void) { while(!q.empty()) { xy=q.front();//出队,开始标记此元素并检测其周围元素是否有@符号 q.pop();//这个……别忘了就好 int X=xy.x; int Y=xy.y; vis[X][Y]=1;//标记 for(int i=0;i<8;i++) { int nx=X+dir[i][0]; int ny=Y+dir[i][1]; if(a[nx][ny]=='@'&&nx>=0&&nx<m&&ny>=0&&ny<n&&vis[nx][ny]==0) { vis[nx][ny]=1; xy.x=nx;xy.y=ny; q.push(xy);//符合条件的将此节点作为起点先推入队,放到后面来检查此节点周围是不是还存在相邻@符 } } } }
唯一两种方法都一次过掉的题,虽然不难但是总要写个博客纪念一下~~~!
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Mootools 1.2教程 函数
- autoit InputBox 函数
- 文件遍历排序函数
- 关于C#中排序函数的总结
- C#递归算法之分而治之策略
- Oracle 函数大全[字符串函数,数学函数,日期函数]第1/4页
- ASP下经常用的字符串等函数参考资料
- PostgreSQL教程(五):函数和操作符详解(1)
- DOS批处理 函数定义与用法
- asp Chr 函数 数字转字母的方法
- Lua中的函数精讲笔记
- Lua中的闭合函数、非全局函数与函数的尾调用详解
- Lua中调用C++函数示例
- Lua和C语言的交互详解
- Lua实现split函数
- Lua常用时间函数使用实例
- Lua函数与字符串处理简明总结
- Lua学习笔记之表和函数