对于这道题,倘如不要求最短路径,用深度优先搜索(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;
}
好了。
其实就加了个第几步。。。。