跳马问题最简路径(最适合初学者的方法,上手就会)(帮你快速理解广度和深度搜索)

对于这道题,倘如不要求最短路径,用深度优先搜索(DFS)即可 

也就是用递归处理,并在递归的过程中存下每一个点的位置,如果失败了,走到了死路。最终会返回上一层,并在循环中将该点的位置覆盖。


现在这个问题的难度升级,如果,要求最短的路径,又该怎么办呢?

利用广度优先搜索(BFS),遍历每一个点,直到最早走到终点。

#include<bits/stdc++.h>
using namespace std;

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

int main()
{
	int w=1,j=1,t=1;
	int lx[10001],ly[10001],jl[10001];
	bool f[9][9]={false};
	int x1,y1,x2,y2;
	cin>>x1>>y1>>x2>>y2;
	lx[1]=x1;
	ly[1]=y1;
	while(1){
		if(lx[t]==x2&&ly[t]==y2){ //已经找到最短路径,依次输出路径 
			cout<<x2<<" "<<y2<<endl;//先输出终点坐标 
			j=jl[t];//找出前一个结点的数组下标 
			while(j>=1){
				cout<<lx[j]<<" "<<ly[j]<<endl; 
				j=jl[j];
			}
			break; 
		}
		else{
			for(int i=1;i<=8;i++){
				if(lx[t]+dx[i]<=8&&lx[t]+dx[i]>0&&ly[t]+dy[i]<=8&&ly[t]+dy[i]>0&&f[lx[t]+dx[i]][ly[t]+dy[i]]==false){//当这个点既不越界,也没有被经过时 
					w++;
					lx[w]=lx[t]+dx[i];
					ly[w]=ly[t]+dy[i];
					jl[w]=t;//用jl这个数组来记录它前一次经过的点的数组下标 
					f[lx[t]+dx[i]][ly[t]+dy[i]]=true;
				}
			}
			t++;
		}
	}
	return 0;
}

这里变量的对应关系是这样的,我觉得如果用结构体应该也不错。

 lx记录路上经过的每一个点的横坐标

ly记录路上经过的每一个点的纵坐标

jl记录路上经过的每一个点的前一个点的下标,便于输出。 

这里注意一个我一开始犯的错误。

第十七行和第十九行的t,不可以写成w!

我一开始想的是在找到终点的那一刻,直接判断出我已经到达了终点,并且开始输出,这样可以简化运算。

 可是,这种方法存在的一个问题是这个w在一个大循环里的变化并不是线性的。中间会有点无法被判断,这也是为什么我一开始编译运行没有输出的原因。

这样说可能过于抽象,举个最简单的例子,比如我的第1个点可以到4个点,其中第2个点是终点,但你的w指向第4个点,最终搜索失败。


接下来我来实践一下自己最初的想法,在过程中判断是否到达终点,这样我可以不用生成整个表,而在过程中就判断是否已经到了终点,这种简化也叫做“剪枝”。

#include<bits/stdc++.h>
using namespace std;

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

int main()
{
	int w=1,j=1,t=1;
	int lx[10001],ly[10001],jl[10001];
	bool f[9][9]={false};
	int x1,y1,x2,y2;
	cin>>x1>>y1>>x2>>y2;
	lx[1]=x1;
	ly[1]=y1;
	while(1){
		if(0);
		else{
			for(int i=1;i<=8;i++){
				if(lx[t]+dx[i]<=8&&lx[t]+dx[i]>0&&ly[t]+dy[i]<=8&&ly[t]+dy[i]>0&&f[lx[t]+dx[i]][ly[t]+dy[i]]==false){//当这个点既不越界,也没有被经过时 
					w++;
					lx[w]=lx[t]+dx[i];
					ly[w]=ly[t]+dy[i];
					jl[w]=t;//用jl这个数组来记录它前一次经过的点的数组下标 
					f[lx[t]+dx[i]][ly[t]+dy[i]]=true;
					if(lx[w]==x2&&ly[w]==y2){ //已经找到最短路径,依次输出路径 
						cout<<x2<<" "<<y2<<endl;//先输出终点坐标 
						j=jl[w];//找出前一个结点的数组下标 
						while(j>=1){
							cout<<lx[j]<<" "<<ly[j]<<endl; 
							j=jl[j];
						}
					break; 
					}
				}
			}
			t++;
		}
	}
	return 0;
}

没想到改一改挺快的。

只要把上面的判断是否抵达终点改到下面,并把t改成w就可以了。


到此,这道题就算圆满解决了。

最后,我在稍微改进一下。让它更完善。

#include<bits/stdc++.h>
using namespace std;

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

int main()
{
	int w=1,j=1,t=1;
	int lx[10001],ly[10001],jl[10001],step[10001]={0};
	bool f[9][9]={false};
	int x1,y1,x2,y2;
	cin>>x1>>y1>>x2>>y2;
	lx[1]=x1;
	ly[1]=y1;
	while(1){
		if(0);
		else{
			for(int i=1;i<=8;i++){
				if(lx[t]+dx[i]<=8&&lx[t]+dx[i]>0&&ly[t]+dy[i]<=8&&ly[t]+dy[i]>0&&f[lx[t]+dx[i]][ly[t]+dy[i]]==false){//当这个点既不越界,也没有被经过时 
					w++;
					lx[w]=lx[t]+dx[i];
					ly[w]=ly[t]+dy[i];
					jl[w]=t;//用jl这个数组来记录它前一次经过的点的数组下标 
					f[lx[t]+dx[i]][ly[t]+dy[i]]=true;
					step[w]=step[t]+1;
					if(lx[w]==x2&&ly[w]==y2){ //已经找到最短路径,依次输出路径 
						cout<<"第"<<step[w]<<"步:"<<x2<<" "<<y2<<endl;//先输出终点坐标 
						j=jl[w];//找出前一个结点的数组下标 
						while(j>=1){
							cout<<"第"<<step[j]<<"步:"<<lx[j]<<" "<<ly[j]<<endl; 
							j=jl[j];
						}
					break; 
					}
				}
			}
			t++;
		}
	}
	return 0;
}

 好了。

其实就加了个第几步。。。。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值