AcWing 175. 电路维修 BFS+双端队列

该博客主要探讨了一种使用宽度优先搜索(BFS)算法来解决网格中寻找最短路径的问题。代码示例展示了如何初始化并遍历网格,更新最短路径,并处理边界条件。博客还提供了参考链接和视频教程以帮助读者更好地理解算法实现。
摘要由CSDN通过智能技术生成

注意边界:
在这里插入图片描述

/*
参考题解:
https://www.acwing.com/solution/content/26973/ 
https://www.acwing.com/solution/content/21775/
观看视频:
https://www.acwing.com/video/132/ 
*/ 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define pb push_back
#define fi first
#define se second
#define mem(a,x) memset(a,x,sizeof(a));
#define db double 
#define fir(i,a,n) for(int i=a;i<=n;i++)
#define debug(x) cout<<#x<<" "<<x<<endl;
const int inf=0x3f3f3f3f;
const int MOD=1e9+7;
//要注意边界范围======================
const int N=510;
int n,m;
char g[N][N];
int ans[N][N];
deque<pii>dq;
int dx[4]={-1,-1,1,1};
int dy[4]={-1,1,-1,1};//格点的四个方向 
int ix[4]={-1,-1,0,0};
int iy[4]={-1,0,-1,0}; 
string idxy="\\//\\";
void bfs()
{
	dq.clear();
	mem(ans,0x3f);
	dq.push_back({0,0});
	ans[0][0]=0;
	while(dq.size())
	{
		auto t=dq.front();
		dq.pop_front();
		
		for(int i=0;i<4;i++)
		{
			int x=t.fi+dx[i];
			int y=t.se+dy[i];
			
			if(x>=0&&x<=n&&y>=0&&y<=m)
			{
				int w=0;//先假设权值为0
				int xx=t.fi+ix[i];
				int yy=t.se+iy[i];
				if(g[xx][yy]!=idxy[i]) w=1;
				if(ans[x][y]>ans[t.fi][t.se]+w)
				{
					ans[x][y]=ans[t.fi][t.se]+w;
					if(w) dq.push_back({x,y});
					else dq.push_front({x,y});
				}
			}
		}
	}
}
int main()
{
	int t;cin>>t;
	while(t--)
	{
		cin>>n>>m;
		for(int i=0;i<n;i++) cin>>g[i];
		bfs();
		if(ans[n][m]==0x3f3f3f3f) cout<<"NO SOLUTION";
		else cout<<ans[n][m];
		cout<<endl;
	}
	return 0; 
}
代码解读void bfs() { while (!q.empty()) { Node cur = q.top(); q.pop(); if (cur.box_x == end_x && cur.box_y == end_y) { best = cur.step; flag = true; break; } else for (int i = 0; i < 4; i++) { flag1 = false; memset(visit2, 0, sizeof(visit2)); int x = cur.box_x + dx[i]; int y = cur.box_y + dy[i]; if (x<1 || y<1 || x>n || y>m || board[x][y] == 1) continue; Node next; next.box_x = x; next.box_y = y; next.people_x = cur.box_x; next.people_y = cur.box_y; next.step = cur.step + 1; if (i == 0) if (cur.box_y - 1 > 0) if (board[cur.box_x][cur.box_y - 1] != 'S' && bfs2(cur.box_x, cur.box_y - 1, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x][cur.box_y - 1]) { visit[x][y][cur.box_x][cur.box_y - 1] = 1; q.push(next); } if (i == 1) if (cur.box_y + 1 <= m) if (board[cur.box_x][cur.box_y + 1] != 'S' && bfs2(cur.box_x, cur.box_y + 1, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x][cur.box_y + 1]) { visit[x][y][cur.box_x][cur.box_y + 1] = 1; q.push(next); } if (i == 2) if (cur.box_x - 1 > 0) if (board[cur.box_x - 1][cur.box_y] != 'S' && bfs2(cur.box_x - 1, cur.box_y, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x - 1][cur.box_y]) { visit[x][y][cur.box_x - 1][cur.box_y] = 1; q.push(next); } if (i == 3) if (cur.box_x + 1 <= n) if (board[cur.box_x + 1][cur.box_y] != 'S' && bfs2(cur.box_x + 1, cur.box_y, cur.box_x, cur.box_y, cur.people_x, cur.people_y) && !visit[x][y][cur.box_x + 1][cur.box_y]) { visit[x][y][cur.box_x + 1][cur.box_y] = 1; q.push(next); } } } }
07-14
这段代码是一个广度优先搜索算法的实现,用于寻找最短路径。下面是代码的解读: 1. 首先,定义了一个名为 `bfs` 的函数,没有返回值(void)。 2. 在函数内部使用了一个 while 循环,判断队列 `q` 是否为空。 3. 在每次循环中,取出队首元素 `cur`,并将其从队列中移除。 4. 判断当前节点的箱子位置是否与目标位置相同,如果是,则更新最佳步数 `best`,设置标志位 `flag` 为 true,并跳出循环。 5. 如果当前节点的箱子位置与目标位置不同,则进行下一步的判断。 6. 使用一个 for 循环遍历四个方向(上、下、左、右)。 7. 首先,将一个名为 `flag1` 的布尔变量设为 false。 8. 使用 memset 函数将数组 `visit2` 的元素全部置为 0,该数组可能用于记录访问状态。 9. 根据当前节点 `cur` 的箱子位置和当前方向计算出下一步的位置 `x` 和 `y`。 10. 如果下一步的位置超出了边界或者是障碍物(`board[x][y] == 1`),则继续下一次循环。 11. 创建一个新的节点 `next`,并将下一步的位置赋值给 `next` 的箱子位置。 12. 将当前节点的人的位置赋值给 `next` 的人的位置。 13. 将当前节点的步数加1,并赋值给 `next` 的步数。 14. 根据当前方向的不同,进行不同的判断和操作: - 如果当前方向是向左移动,并且箱子左边的位置不是墙壁(`board[cur.box_x][cur.box_y - 1] != 'S'`),并且调用了一个名为 `bfs2` 的函数,并且当前位置没有被访问过(`!visit[x][y][cur.box_x][cur.box_y - 1]`),则将 `next` 加入队列 `q` 中,并将对应的访问状态设置为已访问。 - 如果当前方向是向右移动,并且箱子右边的位置不是墙壁(`board[cur.box_x][cur.box_y + 1] != 'S'`),并且调用了一个名为 `bfs2` 的函数,并且当前位置没有被访问过(`!visit[x][y][cur.box_x][cur.box_y + 1]`),则将 `next` 加入队列 `q` 中,并将对应的访问状态设置为已访问。 - 如果当前方向是向上移动,并且箱子上边的位置不是墙壁(`board[cur.box_x - 1][cur.box_y] != 'S'`),并且调用了一个名为 `bfs2` 的函数,并且当前位置没有被访问过(`!visit[x][y][cur.box_x - 1][cur.box_y]`),则将 `next` 加入队列 `q` 中,并将对应的访问状态设置为已访问。 - 如果当前方向是向下移动,并且箱子下边的位置不是墙壁(`board[cur.box_x + 1][cur.box_y] != 'S'`),并且调用了一个名为 `bfs2` 的函数,并且当前位置没有被访问过(`!visit[x][y][cur.box_x + 1][cur.box_y]`),则将 `next` 加入队列 `q` 中,并将对应的访问状态设置为已访问。 15. 循环结束后,函数执行完毕。 此处代码片段并不完整,缺少了定义和初始化一些变量的部分,例如队列 `q`、数组 `dx` 和 `dy`、数组 `visit`、数组 `board` 等。同时,函数内部还调用了一个名为 `bfs2` 的函数,但在提供的代码中并没有给出其实现。因此,对于代码的完整性和准确性还需要进一步的了解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值