接続されたブロックを検索する(BFS、DFSの例)

トピック:

mxn行列が与えられると、行列の要素は0または1になります。位置(x、y)は、その4つの位置(x、y + 1)、(x、y-1)(x + 1、y)(x-1、y)に隣接していると言われています。マトリックス内に隣接する(必ずしも互いに隣接している必要はない)複数の1がある場合、これらの1は「ブロック」を形成すると言われます。与えられた行列の「ブロック」の数を見つけます。
ここに画像の説明を挿入します

はじめに:考えを記録して、後で戻って確認できるようにします

アイデアとポイント:

1.方向増分の配列を設定します。

int X[] = {
    
     0,0,1,-1 };		//方向增量数组
int Y[] = {
    
     1,-1,0,0 };

2.ポイント座標を記録するための構造を設定します(ペアも利用可能)

struct nod
{
    
    
	int x, y;
}node;

3.すべてのポイントにアクセスしたかどうかを記録し、ポイントにアクセスしてチームに入れ、一時変数を使用して保存し、チームからポップして、4方向の要素を幅広く検索してから、チームを個別に作成します。bool配列を使用して、特定の要素がキューに入れられているかどうかを保存します。最初はすべてFALSEです。

bool inq[6][7] = {
    
     false };				//判断元素是否入队

void bfs(int x, int y)	//BFS算法
{
    
    
	queue<nod>q;		//nod型队列
	node.x = x, node.y = y;	//实参传递
	q.push(node);
	inq[x][y] = true;
	while (!q.empty())
	{
    
    
		nod top = q.front();		//取出栈顶
		q.pop();					//栈顶出栈
		for (int i = 0; i < 4; i++)	//四个方向
		{
    
    
			int newx = top.x + X[i];
			int newy = top.y + Y[i];
			if (judge(newx, newy))		//如果说遍历的这个点需要访问
			{
    
    
				node.x = newx, node.y = newy;
				q.push(node);
				inq[newx][newy] = true;
			}
		}
	}
}

4.訪問するたびにBFSを入力する必要はありません。訪問する必要があるかどうかを判断するためのジャッジ関数を作成します。ポイントがすでにチームに入っているか、境界を超えている場合は、スキップします。

int main()
{
    
    
	int ans = 0;		//存放块数的答案
	for (int i = 0; i < 6; i++)
		for (int j = 0; j < 7; j++)
		{
    
    
			if (a[i][j] == 1 && inq[i][j] == false)//如果没被入队过并且点权等于1,那么就BFS,否则就下一个a[i][j]
			{
    
    
				ans++;
				bfs(i, j);
			}
		}
}

またはBFSでのアクセス判断:

bool judge(int x, int y)
{
    
    
	if (x >= 6 || x < 0 || y >= 7 || y < 0) return false;
	if (inq[x][y] == true || a[x][y] == 0) return false;
	//都不符合情况, 返回真
	return true;
}

BFSの完全な実装コード:

#include<algorithm>
#include<stdio.h>
#include<string.h>
#include <iostream>
#include<string>
#include<queue>
using namespace std;

struct nod
{
    
    
	int x, y;
}node;

int X[] = {
    
     0,0,1,-1 };		//方向增量数组
int Y[] = {
    
     1,-1,0,0 };

int a[6][7] = {
    
    			//01地图矩阵
			{
    
    0,1,1,1,0,0,1},
			{
    
    0,0,1,0,0,0,0},
			{
    
    0,0,0,0,1,0,0},
			{
    
    0,0,0,1,1,1,0},
			{
    
    1,1,1,0,1,0,0},
			{
    
    1,1,1,1,0,0,0}
};

bool inq[6][7] = {
    
     false };				//判断元素是否入队

bool judge(int x, int y)
{
    
    
	if (x >= 6 || x < 0 || y >= 7 || y < 0) return false;
	if (inq[x][y] == true || a[x][y] == 0) return false;
	//都不符合情况, 返回真
	return true;
}

void bfs(int x, int y)
{
    
    
	queue<nod>q;		//nod型队列
	node.x = x, node.y = y;	//实参传递
	q.push(node);
	inq[x][y] = true;
	while (!q.empty())
	{
    
    
		nod top = q.front();		//取出栈顶
		q.pop();					//栈顶出栈
		for (int i = 0; i < 4; i++)	//四个方向
		{
    
    
			int newx = top.x + X[i];
			int newy = top.y + Y[i];
			if (judge(newx, newy))		//如果说遍历的这个点需要访问
			{
    
    
				node.x = newx, node.y = newy;
				q.push(node);
				inq[newx][newy] = true;
			}
		}
	}
}

int main()
{
    
    
	int ans = 0;		//存放块数
	for (int i = 0; i < 6; i++)
		for (int j = 0; j < 7; j++)
		{
    
    
			if (a[i][j] == 1 && inq[i][j] == false)
			{
    
    
				ans++;
				bfs(i, j);
			}
		}
	for (int i = 0; i < 6; i++) {
    
    
		for (int j = 0; j < 7; j++)
			cout << a[i][j] << " ";
		cout << endl<<endl;
	}
	cout << "一共"<<ans<<"个联通分块!";
	return 0;
}

DFS関数の実装:(dfsによって使用されるスタック)

void dfs(int x, int y)
{
    
    
	stack<nod>w;		//队列	
	node.x = x, node.y = y;
	w.push(node);		//进栈
	inq[x][y] = true;	//记录进栈
	for (int i = 0; i < 4; i++)
	{
    
    
		if (judge(x + X[i], y + Y[i]))//符合条件就DFS
		{
    
    
			dfs(x + X[i], y + Y[i]);
		}
	}
	w.pop();		//如果四个方向访问后退回,代表没有路走了,出栈
}

テスト:

あとがき:35日

おすすめ

転載: blog.csdn.net/Kyrie_irving_kun/article/details/114790371