蓝桥杯dfs--最短距离总结反思

本文通过一道编程题讲述了如何优化广度优先搜索(BFS)算法来解决大型矩阵中求0到1的最短距离问题。作者反思了自己在算法应用上的固定思维,并分享了一位大佬的高效解决方案:从1出发进行BFS,避免了重复计算,显著提高了效率。此外,还讨论了代码风格和模板的灵活性。
摘要由CSDN通过智能技术生成

题目:

给定一个n*m的矩阵,求每个0距离任意的1的最短距离

这里的距离定义为曼哈顿距离,即|x| + |y|

Input
第一行两个整数n,m。 (1 <= n,m <= 1000)

接下来一个N行M列的01矩阵,数字之间没有空格。

Output
一个N行M列的矩阵,相邻两个整数之间用一个空格隔开。

Sample Input 1

4 4
0010
1001
1000
0000
Sample Output 1

1 1 0 1
0 1 1 0
0 1 2 1
1 2 3 2

反思:
我发现我每学会一个算法,就总是习惯使用那种最常规的框架,框架尽管能让我对题目有一个大体的方向,但这也是有弊端的我觉得,这容易让我有一种定性思维,每次都那么做,这其实是不太好的我个人认为。再者,我觉得,一类题一个是多做同种类型的;再就是,多总结反思可以灵活运用各个题之间的代码思路相互结合,这点我做的还是不够好。我做的题还是少啊。

这道题我开始是用的常规思路,就是以每个 0 为起点,逐个bfs,找到最近的1就结束,尽管这个思路是对的,但是在这么大的数据量下,又结合入栈出栈,不难想到一定会超时

我开始写的代码:

#include"iostream"
#include"queue"
#include"cstring"
using namespace std;
int n, m, g;
int a[1005][1005];
int xx[4] = {-1,0,1,0}, yy[4]= {0,1,0,-1};
int vis[1005][1005];
struct point{
	int x,y,step;
	point(int xx,int yy,int ss){
		x = xx;
		y = yy;
		step = ss;
	}
};
void bfs(int cx,int cy){
	queue<point> q;
	q.push(point(cx,cy,0));
	vis[cx][cy] = 1;
	
	while(!q.empty()){
		point p = q.front();
		q.pop();
		
		if(a[p.x][p.y] == 1){
			g = p.step;
			return;
		}
		
		for(int i = 0;i < 4;i ++){
			int tx = p.x + xx[i];
			int ty = p.y + yy[i];
			
			if(vis[tx][ty] != 1 && tx>= 0 && tx <n && ty >= 0 && ty < m){
				vis[tx][ty] = 1;
				q.push(point(tx,ty,p.step+1));
 			}
		}
	}
}
int main(){
	cin >> n >> m;
	string s;
	
	for(int i = 0;i < n;i ++){
		cin >> s;
		for(int j = 0;j < m;j ++){
			a[i][j] = s[j]-48;
		}
	}
	
	
	for(int i = 0;i < n;i ++){
		for(int j = 0;j < m;j ++){
			if(a[i][j] == 1) cout << 0 << " ";
			else{
				memset(vis,0,sizeof(vis));
				bfs(i,j);
				cout << g << " ";
			}
			
		}
		
		cout << endl;
	}
	
	return 0;
}

尽管说我在这上面做了一些优化,但是是远远不够的。

借鉴大佬的代码:

#include"iostream"
#include"utility"  // pair 的头文件
#include"queue"
#include"cstring"
using namespace std;
int n, m;
int xx[4] = {-1,0,1,0}, yy[4]={0,1,0,-1};
int a[1005][1005];
int dist[1005][1005];
pair<int,int> cur;
queue<pair<int,int> > q;
int main(){
	cin >> n >> m;
	string s;
	memset(dist,-1,sizeof(dist));
	for(int i = 0;i < n;i ++){
		cin >> s;
		for(int j = 0;j < m;j ++){
			if(s[j] == '1'){
				q.push(make_pair(i,j));
				dist[i][j] = 0;	
			} 
		}
	}
	
	while(!q.empty()){
		cur = q.front();
		q.pop();
		
		for(int i = 0;i < 4;i ++){
			int tx = cur.first + xx[i];
			int ty = cur.second + yy[i];
			
			if(tx>=0 && tx<n && ty>=0 && ty<m && dist[tx][ty] == -1){
				dist[tx][ty] = dist[cur.first][cur.second] + 1; // 此时的dist[cur.first][cur.second]在开始是为0的     这里的理解要对应到输入是的 s[j] == '1' 的判断那里
				q.push(make_pair(tx,ty));
			}
		}
	}
	
	for(int i = 0;i < n;i ++){
		for(int j = 0;j < m;j ++){
			cout << dist[i][j] << " ";
		}
		cout<< endl;
	}
	
	return 0;
}

大佬的代码值得借鉴的地方:
1.首先是他的解题思想,很好,是从1开始bfs,但是一般我感觉首先容易想到的是bfs 0(尽管超时),在我看来这就是思想上的进步,每次做题的时候就应该事先多考虑一下,到底先对谁bfs更好,这一点真的很重要,会少走不少弯路。
2.他的bfs的写作模板也是值得借鉴的,我之前写bfs总是习惯于另外再写一个方法,不过今天看了他的代码我觉得以后我也可以尝试一下他的这种风格。

世界很大,一个家很小,但有一点是一样的,唯有爱能让它变得更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Rabbit Coder

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

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

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

打赏作者

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

抵扣说明:

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

余额充值