01BFS:小明的游戏

普通的bfs:解决边权为1的最短路问题。从0的点开始往后更新,因为边权为1,所以呈现单调不递减的趋势。

第一次碰到的距离一定是最短距离,如果边权不相等,不一定是单调不递减趋势,第一次碰到的距离不一定是最短距离。

01BFS又称双端队列BFS

既有0,又有1,能不能用BFS来解决呢?在最短路问题中,边权值可能为1也可能为0。那么,在BFS的过程中,

  • 可以将边权为0 的扩展出来的点放到队首
  • 边权为1 扩展出来的点放到队尾

这样就能保证像普通BFS一样整个队列权值单调不下降。

相同的点可能会多次遇到,此时要进行松弛操作,比如从A->B,从A->C->E->B,这两条路线都能到达B,此时要判断哪一条的路线是最优解。

题目:P4554 小明的游戏 - 洛谷

cpp 复制代码
#include <iostream>
#include <deque> 
#include <cstring>

using namespace std;
const int N = 510;
typedef pair<int, int> PII;

int n, m;
int b1, b2, e1, e2;
char a[N][N];
int st[N][N];

int dx[] = {0, -1, 0, 1};
int dy[] = {1, 0, -1, 0};

int bfs()
{
	if (b1 == e1 && b2 == e2) return 0;
	
	deque<PII> q;
	memset(st, -1, sizeof(st));
	
	st[b1][b2] = 0;
	q.push_front({b1, b2});
	
	while(q.size())
	{
		auto t = q.front(); q.pop_front();
		int x1 = t.first, y1 = t.second;
		
		for (int i = 0; i < 4; i++)
		{
			int x2 = x1 + dx[i], y2 = y1 + dy[i];
			if (x2 < 1 || y2 < 1 || x2 > n || y2 > m) continue;
			
			int cnt = 0;
			if (a[x1][y1] == a[x2][y2]) 
			{
				cnt = 0;
			}
			else
			{
				cnt = 1;
			}
			
			if (st[x2][y2] == -1)//如果等于-1 
			{
				st[x2][y2] = st[x1][y1] + cnt;
				if (cnt == 0)
				{
					q.push_front({x2, y2});
				}
				else
				{
					q.push_back({x2, y2});
				}
			}
			else
			{
				if (st[x1][y1] + cnt < st[x2][y2])
				{
					st[x2][y2] = st[x1][y1] + cnt;
				}
			}
			
			if (x2 == e1 && y2 == e2) return st[e1][e2];
		}
	}
	
	return -1;
}

int main()
{	
	while(cin >> n >> m, n && m)
	{
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= m; j++)
			{
				cin >> a[i][j];
			}
		}
		
		cin >> b1 >> b2 >> e1 >> e2;
		b1++, b2++, e1++, e2++;
		
		cout << bfs() << endl;
	}
	
	return 0;
}

为什么第一次走到的一定是最短路径?边权不是0和1吗?

0-1 BFS(双端队列BFS)的核心性质保证了这一点:

队列的单调性

  • 在0-1 BFS中,我们使用双端队列(deque)
  • 当边权为0时,节点放入队首
  • 当边权为1时,节点放入队尾

这样的操作保证了队列中的距离值(st值)是单调不递减的

相关推荐
falldeep2 小时前
Claude Code源码分析
人工智能·算法·机器学习·强化学习
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2026.04.14 题目:2463.最小移动距离
笔记·算法·leetcode
feng_you_ying_li2 小时前
C++11可变模板参数,包扩展,emplace系列和push系列的区别
前端·c++·算法
tankeven2 小时前
HJ177 可匹配子段计数
c++·算法
剑挑星河月2 小时前
55.跳跃游戏
数据结构·算法·leetcode
Gofarlic_OMS2 小时前
中小企业控制方法:中小型制造企业Creo许可证成本控制
java·大数据·运维·算法·matlab·制造
星马梦缘2 小时前
快表、页表地址获取+缓存、主存、硬盘数据获取
算法·操作系统·os·tlb
大尚来也2 小时前
Go性能优化实战:如何减少内存分配,榨干每一滴性能
算法