Oil Deposits——HDU - 1241

了解题目

题目链接

Oil Deposits - HDU 1241 - Virtual Judgeicon-default.png?t=N7T8https://vjudge.csgrandeur.cn/problem/HDU-1241Problem - 1241icon-default.png?t=N7T8https://acm.hdu.edu.cn/showproblem.php?pid=1241

题目

        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.

输入格式

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.

输出格式   

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.

分析题目

题目翻译

        下面GeoSurvComp地质调查公司负责探测地下石油储量。GeoSurvComp一次处理一个大型矩形区域,并创建一个网格,将土地划分为许多方形地块。然后,它分别分析每个地块,使用传感设备确定地块是否含有石油。含有石油的阴谋被称为口袋。如果两个口袋相邻,那么它们是同一个油藏的一部分。油藏可能很大,可能包含许多口袋。你的工作是确定一个网格中包含多少个不同的油藏。

输入格式翻译

输入文件包含一个或多个网格。每个网格以包含m和n的行开始,m和n是网格中的行数和列数,由单个空格分隔。如果m=0,则表示输入结束;否则,1 <= m <= 100且1 <= n <= 100。接下来是 m 行,每行 n 个字符(不包括行尾字符)。每个字符对应一个地块,代表没有石油的“*”,或代表油藏的“@”

输出格式翻译    

对于每个网格,输出不同油藏的数量。如果两个不同的油藏水平、垂直或对角相邻,则它们是同一个油藏的一部分。一个油藏包含的油囊不能超过100个。

相似例题

有一个矩阵,其中字母“@”代表岛屿,“*”代表海洋,一块陆地的上下左右相邻均为陆地,则算作同一块陆地,求有几块陆地。 

输入样例        

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5 
****@
*@@*@
*@**@
@@@*@
@@**@
0 0 

输出样例

0
1
2
2

解题思路

  • 首先我们需要输入n,m以及一个录入含有“@"和“*”的关系的矩阵,一个矩阵用来记录是否访问过,(可以简化成一个矩阵,即直接修改原来矩阵)。
  • 找出一个元素为“@”且未访问过的元素,开始进行BFS搜索,标记该元素所在的连通块。
  • 继续寻找未访问过的“@”元素,如果有,则找到下一个连通块,继续进行BFS搜索,标记该连通块。
  • 记录连通块的个数,即为答案。

代码(c++防抄)

#include<iostream>
#include<queue>
#include<cstring>

using namespace std;
#define int long long
#define endl "\n"
const int n = 101;
int arr[n][n] = {0}, vis[n][n] = {0};
int dx[] = {0, 0, 1, -1, 1, 1, -1, -1};
int dy[] = {1, -1, 0, 0, 1, -1, 1, -1 };
int x, y;
char ch;
int cnt = 0;
struct node {
	int x, y;
	node(int x,int y):x(x),y(y){}
	node(){}
};
bool check(int x, int y)
{
	return x >= 0 && x < y;
}
void bfs(int xx, int yy)
{
	queue<node> q;
	q.push(node(xx,yy));

	while (!q.empty()) {
		node t = q.front();
		q.pop();

		for (int i = 0; i < 8; i++) {
			int tx = t.x + dx[i];
			int ty = t.y + dy[i];
			if (tx >= 0 && tx < x && ty >= 0 && ty < y && arr[tx][ty] == 1 && vis[tx][ty] == 0) {
				vis[tx][ty] = cnt;
				q.push(node(tx,ty));
			}
		}

	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	while (cin >> x >> y, x + y > 1) {
		cnt = 0;
		memset(arr, 0, sizeof arr);
		memset(vis, 0, sizeof vis);

		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y; j++) {
				scanf("%c",&ch);
				if (ch == '*') {
					arr[i][j] = 0;
				} else if (ch == '@') {
					arr[i][j] = 1;
				}
			}
		}


		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y; j++) {
				if (arr[i][j] == 1 && vis[i][j] == 0) {
					cnt ++;
					bfs(i, j);
				}
			}
		}
		cout << cnt << endl;
	}

	return 0;
}

题目总结

知识点

       图论——BFS(广搜)或 DFS

BFS

  • 首先将起始节点加入队列。
  • 当队列非空时,取出队首节点。
  • 遍历队首节点的所有邻居节点,如果邻居节点未被访问,则将邻居节点加入队列,标记为已访问。
  • 重复步骤2、3,直到队列为空。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值