贪吃蛇--dfs与bfs初步学习

标题 贪吃蛇–dfs与bfs对比学习(适合初学小白)

题目地址
贪吃蛇 link
https://ac.nowcoder.com/acm/contest/9986/I
链接:https://ac.nowcoder.com/acm/contest/9986/I
来源:牛客网

题目描述
无限增长的贪吃蛇小游戏:

在一个n*m的迷宫中,有一条小蛇,地图中有很多围墙,猥琐的出题者用“#”表示,而可以走的路用“.”表示,小蛇他随机出生在一个点上,出生点表示为“S”,他想抵达的终点表示为“E”,小蛇有一个奇怪的能力,他每走一格便会增长一格,即他走了一格后,他的尾巴不会缩回。

小蛇想知道他怎么到达他想去的地方,请你帮助他。

PS:每格长1米,贪吃蛇规定不能撞墙,不能咬自己的身体。
输入描述:
第一行:输入N,M;

第二行:输入S的坐标Xs,Ys,E的坐标Xe,Ye;

后面的N行:

每行输入M个数,描述每一行的情况。

输出描述:
输出一个数,小蛇到达终点的最短距离(单位:cm),若无法达到,输出-1
示例1
输入
复制
3 3
1 1 3 3
.#.
.#.

输出
复制
400
示例2
输入
复制
5 5
1 1 5 5
…###
.#…
.#.#.
.#.#.
…#.
输出
复制
1400
备注:
对于 100% 的数据:1\le n,m\le 1001≤n,m≤100 ,保证起点不是围墙。

思路
*1.*bfs与dfs都可以解决,但是不同的方式都会遇见相同的问题:距离怎么表示,如何求最近的距离
*2.*对于bfs 他每一次将可以移动的地方记录下来,也就是说一个点到周围可以移动的点他都会先遍历一遍,然后再走,所以我们可以吧vis数组改一下(本来是用来记录是否走过,防止来回移动),将他改成在记录改点的距离的数据,也就是说vis是记录这个点是起点移动几步得到的。
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int M = 110;
int vis[110][110];
int m,n,xs,ys,ye,xe,ok; //初始数据 
char Map[110][110];
struct node{
	int xx;
	int yy; 
};//表示坐标 
int dx[4] = {-1,0,1,0};
int dy[4] = {0,-1,0,1};
void bfs(){
	queue<node> q;
	node beg,ll;//beg是将起点变成node的类型,不然queue不认识,见面就打架
				//ll也是转换,就是新得到出来的点 转换,详情往下看 
	beg.xx=xs;
	beg.yy=ys;
	q.push(beg);
	vis[xs][ys] = 0;
	while(!q.empty()){
		node top = q.front();
		q.pop();
		if(top.xx==xe&&top.yy==ye) {
			ok = 1;
			return ;
		}
		for(int i = 0;i<4;i++){
			int xx = top.xx+dx[i];
			int yy = top.yy+dy[i];
			if(xx>=1&&xx<=n&&yy>=1&&yy<=m){
				if(vis[xx][yy] == -1&&Map[xx][yy]!='#'){
				vis[xx][yy] = vis[top.xx][top.yy]+1; //与普通bfs区别 就在这,没错,理解这里就okk了。 
				ll.xx = xx;
				ll.yy = yy;
				q.push(ll);
				}
			}
		}	
	}
	
}
int main(){
	scanf("%d%d%d%d%d%d",&n,&m,&xs,&ys,&xe,&ye);
	for(int i = 1;i<=n;i++){
		scanf(" ");
		for(int j = 1;j<=m;j++)
		scanf("%c",&Map[i][j]);
	}
	memset(vis,-1,sizeof vis);
	bfs();
	if(!ok) cout<<-1<<endl;
	else
	cout<<(vis[xe][ye])*100<<endl;
	return 0;
}

哎呀,说那么多,其实只要理解了vis[xx][yy] = vis[top.xx][top.yy]+1就可以明白了。
*3.*dfs要注意一条路走过之后,还能被另一种方案走,也就是一个点可能被用多次,所有当这个点遍历完,还是要出来的。
代码如下

#include<bits/stdc++.h>
using namespace std;
int n,m,xs,ys,xe,ye; //初始读入 
const int INF  = 0x4f4f4f4f; //设置最大值 
int vis[110][110];  //记录是否走过
char Map[110][110]; 
struct node{
	int xx,yy;
	bool operator==(const node& nw){	//定义 相等 
		return (nw.xx==xx&&nw.yy==yy);  
	}
}be,en; //起点和终点 
int maxs = INF,ok;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void dfs(node t,int dis){
	if(t == en){
		maxs = min(dis,maxs);
		ok = 1; 
	}
	int xx,yy;
	vis[t.xx][t.yy] = 1; 
	for(int i = 0;i<4;i++){
		xx = t.xx+dx[i];
		yy = t.yy+dy[i];
		if(xx>0&&xx<=n&&yy>0&&yy<=m&&vis[xx][yy]==0&&Map[xx][yy]!='#'){
			node go;
			go.xx=xx;
			go.yy=yy;
			vis[xx][yy] = 1; 
			dfs(go,dis+1);
			//与简单的dfs区别就是这了,没错!!! 
			vis[xx][yy] = 0; //出来后表示回去,因此这条路也就不能算走过了 
		}
	}

}
int main(){
	scanf("%d%d",&n,&m);
	scanf("%d%d%d%d",&xs,&ys,&xe,&ye);
	be.xx = xs;
	be.yy = ys;
	en.xx = xe;
	en.yy = ye;
	for(int i = 1;i<=n;i++){
		scanf(" ");
		for(int j = 1;j<=m;j++){
			scanf("%c",&Map[i][j]);
		}
	}
	dfs(be,0);
	
	if(ok)
	cout<<maxs*100<<endl;
	else cout<<-1<<endl;
	return 0;
} 

又到了让我期待的 总结
对比上面两个代码,会发现,bfs只要第一次找到了出口,就是最短的距离,而dfs还是要跑完整张图,可能有优化方法我没想到。。。
总而言之,建议在于最短路程相关的遍历时还是用bfs更好,更方便。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

手撕键盘

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

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

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

打赏作者

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

抵扣说明:

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

余额充值