搜索

bfs

1.求最小

2.基于迭代

Flood Fill

“洪水填充法”

对于一个凹凸的地形图,每次选择一个凹进去的格子(想象有一个无穷大的格子),那么水会慢慢覆盖掉周围所有的洼地。这个覆盖过程是按照bfs的顺序进行的。(你想按深度dfs顺序覆盖也没人拦你,只不过可能爆栈)

效果:可以在线性时间复杂度内,找到某个点所在的连通块

池塘计数

#include <bits/stdc++.h>
using namespace std;
#define xx first
#define yy second
const int N = 1005;
/*wc,想用并查集,忍住了*/
int rx[10] = {-1, 1, 0, 0, 1, 1, -1, -1};
int ry[10] = {0, 0, -1, 1, 1, -1, 1, -1};
char mp[N][N];
int n, m, a[N][N], cnt = 0;
queue<pair<int, int> > q;
void bfs(int u, int v)
{
	q.push(make_pair(u, v));
	a[u][v] = ++ cnt;
	while(!q.empty())
	{
		u = q.front().xx, v = q.front().yy;
		q.pop();
		for (int i = 0; i < 8; ++ i)
		{
			int nx = u + rx[i], ny = v + ry[i];
			if(nx <= 0 || ny <= 0 || nx > n || ny > m) continue;
			if(!a[nx][ny] && mp[nx][ny] == 'W') a[nx][ny] = cnt, q.push(make_pair(nx, ny));
		}
	}
	return ;
} 
int main()
{
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; ++ i) scanf("%s", mp[i] + 1);
	for (int i = 1; i <= n; ++ i)
	{
		for (int j = 1; j <= m; ++ j)
		{
			if(a[i][j] == 0 && mp[i][j] == 'W') bfs(i, j);
		}
	}
	printf("%d", cnt);
	return 0;
}

城堡问题

/*
(x, y) -> (x, y + 1) 没有4, 没有1 右 

(x, y) -> (x, y - 1)没有1, 没有4 左 

(x, y) -> (x + 1, y) 没有8 没有2 下 

(x, y) -> (x - 1, y) 没有2 没有8 上 
 
没有说明 & 的时候结果为0 
*/
#include <bits/stdc++.h>
using namespace std;
#define xx first
#define yy second
const int N= 55;
int n, m, a[N][N], b[N][N], cnt = 0, ans = 0;
int rx[5] = {-1, 1, 0, 0};
int ry[5] = {0, 0, -1, 1};
int pdx[5] = {2, 8, 1, 4};
int pdy[5] = {8, 2, 4, 1};
queue<pair<int, int> > q;
void bfs(int u, int v)
{
	int sum = 1;
	q.push(make_pair(u, v));
	b[u][v] = ++ cnt;
	while(!q.empty())
	{
		u = q.front().xx, v = q.front().yy;
		q.pop();
		for (int i = 0; i < 4; ++ i)
		{
			int x = u + rx[i], y = v + ry[i];
			if(x <= 0 || y <= 0 || x > n ||y > m || b[x][y]) continue;
			if(!(a[u][v] & pdx[i]) && !(a[x][y] & pdy[i])) b[x][y] = cnt, q.push(make_pair(x, y)), sum ++; 
		}
	}
	ans = max(ans, sum);
	return ;
}
int main()
{
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; ++ i)
	{
		for (int j = 1; j <= m; ++ j) scanf("%d", &a[i][j]);
	}
	for (int i = 1; i <= n; ++ i)
	{
		for (int j = 1; j <= m; ++ j) 
		{
			if(!b[i][j]) bfs(i, j);
		}
	}
	printf("%d\n%d", cnt, ans);
	return 0;
}

多源bfs

矩阵距离

这个题目需要我们求距离最近的1的曼哈顿距离。就相当于所有的1都是源点,然后求该点到源点的最短距离。直接把源点都放进初始的队列中就可以了。

#include <bits/stdc++.h>
using namespace std;
#define fir first
#define sec second 
const int N = 1005;
int n, m, dis[N][N];
char a[N][N];
bool vis[N][N];
int rx[5] = {-1, 1, 0, 0};
int ry[5] = {0, 0, -1, 1};
int main()
{
	scanf("%d %d", &n, &m);
	queue<pair<int, int> > q;
	for (int i = 1; i <= n; ++ i)
	{
		scanf("%s", a[i] + 1);
		for (int j = 1; j <= m; ++ j) 
		{
			if(a[i][j] == '1') vis[i][j] = 1, dis[i][j] = 0, q.push(make_pair(i, j));
		}
	}	
	while(!q.empty())
	{
		int x = q.front().fir, y = q.front().sec;
		q.pop();
		for (int i = 0; i < 4; ++ i)
		{
			int nx = x + rx[i], ny = y + ry[i];
			if(nx <= 0 || ny <= 0 || nx > n || ny > m || vis[nx][ny]) continue;
			vis[nx][ny] = 1;
			q.push(make_pair(nx, ny));
			dis[nx][ny] = dis[x][y] + 1;
		}
	}
	for (int i = 1; i <= n; ++ i)
	{
		for (int j = 1; j <= m; ++ j)
		{
			printf("%d ", dis[i][j]);
		}
		printf("\n");
	}
	return 0;
}

最小步数模型

最小步数模型一般是对一个状态进行操作,求这个状态变成另外一个新状态所需要的最小的步数。

#include <bits/stdc++.h>
using namespace std;
int f[5][10] = 
{
	{7, 6, 5, 4, 3, 2, 1, 0}, 
	{3, 0, 1, 2, 5, 6, 7, 4}, 
	{0, 6, 1, 3, 4, 2, 5, 7}
};
char s[5] = {' ', 'A', 'B', 'C'};
map<int, int> vis, pre;
int n, g = 0;
vector<char> path;
struct node
{
	int a[8], num;
}p;
queue<node> q;
void bfs()
{
	p.num = 0;
	for (int i = 0; i < 8; ++ i) p.a[i] = i, p.num = p.num * 10 + i;
	vis[p.num] = -1, pre[p.num] = -1;
	q.push(p);
	while(!q.empty())
	{
		node x = q.front();
		q.pop();
		for (int i = 0; i < 3; ++ i)
		{
			node y; y.num = 0;
			for (int j = 0; j < 8; ++ j) 
			{
				y.a[j] = x.a[f[i][j]];
				y.num = y.num * 10 + y.a[j];
			}
			if(!vis.count(y.num)) 
			{
				vis[y.num] = i + 1, pre[y.num] = x.num;
				q.push(y);
			}
		}
		if(vis.count(g)) break;
	}
	return ;
}
void dfs(int x)
{
	if(x == -1) return ;
	dfs(pre[x]);
	path.push_back(s[vis[x]]);
}
int main()
{
	int x;
	for (int i = 0; i < 8; ++ i) 
	{
		scanf("%d", &x);
		g = g * 10 + (x - 1);
	}
	bfs();
	dfs(g);
	printf("%d\n", path.size() - 1);
	for (int i = 1; i < path.size(); ++ i)
	{
		printf("%c", path[i]);
	}
	return 0;
}
posted @ 2025-02-13 10:38  Helioca  阅读(8)  评论(0)    收藏  举报
Document