废话不多说上题目:
【题目部分】
有一个mn格的迷宫(表示有m行、n列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可走,文件读入这mn个数据和起始点、结束点(起始点和结束点都是用两个数据来描述的,分别表示这个点的的行号和列号)。现在要你编程找出所有可行的道路总数,要求所走的路中没有重复的点,走时只能是上下左右四个方向。如果一条路都不可行,则输出相应信息(用 -1表示无路)。
Input
第一行是两个数 m、n(1 < m,n < 15),接下来是m行n列由10组成的数据,最后两行是起始点和结束点。
Output
所有可行的路径总数。如果没有一条可行的路则输出 -1.
Sample Input 1
5 6 1 0 0 1 0 1 1 1 1 1 1 1 0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 0 1 1 1 1 5 6
Sample Output 1
12
第一次看到这个题目,我的内心是:这什么东西讲的啥,一点都听不懂,直接不做了。
但是让我讲个东西你和我可能就明白了:
迷宫类的搜索,需要一些处理技巧。
对于迷宫类的搜索,假设当前点为 i ,j ,按照本题迷宫的走法,它可以向上下左右四个方向走动:
1、迷宫边界问题
因为在走的过程中,可能会走出迷宫边界,所以每走一步都需要判断是否是边界,比如向上走,可能会超出上边界,向下走可能会超出下边界等等。常规的办法就是判断走到的点的坐标是否在迷宫内部,但是比较繁琐。
一种处理的技巧就是对给定的迷宫四周加个围墙,对于本题,所谓围墙就是把迷宫的四周都赋值为0,相当于把迷宫外围一圈都设置为不可走
这样在程序处理时的好处:不用考虑边界问题(因为边界的位置是0,走不了),程序就会简洁多了。
迷宫边界?处理?判断?
bool m[20][20];
用0或false在m数组中表示边界或不能走的地方,既然要加一个围墙,那么读入的时候就要注意一个小细节:
for(int i=1;i<= m;i++) //迷宫从第一行开始存放
for(int j=1;j<= n;j++) //迷宫从第一列开始存放
cin>>m[i][j];
为什么i,j都是从1开始呢?因为有个围墙啊( ⊙ o ⊙ )!
自己理解吧qwq
2、四个方向的处理
常规的做法是四个方向分别处理
比如:void mg(int x,int y){........}
向上走:mg(x-1,y);
向右走:mg(x,y+1);
.....
这样需要调用四次,一种巧妙的做法是设置增量数组,原理是对当前点来说:
如果向上走,行 -1 ,行增量就是 -1;列 不变,列增量就是 0;
如果向左走,行 不变,行增量就是 0 ;列 -1 ,列增量就是-1;
如果向下走,行 +1 ,行增量就是 +1;列 不变,列增量就是 0;
如果向右走,行 不变,行增量就是 0 ;列 +1 ,列增量就是+1;
然后用一个数组存行的增量,另一个数组存列的增量,比如下面的写法:
int dx[]={-1,0,1,0};//上左下右四个方向的行增量
int dy[]={0,-1,0,1};//上左下右四个方向的列增量
比如:void mg(int x,int y){........}
四个方向的走动就可以用循环处理:
for(int i=0;i<4;i++)
mg(x+dx[i],y+dy[i]);
这样看完是不是就有一个代码的基础框架在我们的脑海里浮现了呢?反正我当时没感觉
我们先处理边界问题,之后运用回溯算法(推个文章NO.1,NO.2)对要走的方向进行试探(递归?),直到碰到死胡同(0或false),返回(return),对另一个方向进行试探...
上代码:
#include<bits/stdc++.h>
using namespace std;
bool ma[25][25];//ma即map用来标记走过的路
int bk[4]={0,0,1,-1},dy[4]={-1,1,0,0};//增量数组
int n,m,ax,ay,bx,by,w[25][25],ans=0;//w即walk用来储存迷宫图案
//ax,ay是起点的坐标,bx,by是终点坐标
bool bj;//负责查看有没有至少一条路径
void dfs(int a,int b){
if(a==bx&&b==by){//如果到达终点
bj=1;//标记
ans++;//方案++
return ;//返回
}
for(int i=0;i<4;i++){
if(ma[a+bk[i]][b+dy[i]]==0&&w[a+bk[i]][b+dy[i]]==1){
//判断是否走过并且要走的方向没有障碍物(墙?)
ma[a][b]=1;//标记
dfs(a+bk[i],b+dy[i]);//继续试探
ma[a][b]=0;//回溯一步
}
}
return ;//结束
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>w[i][j];
cin>>ax>>ay>>bx>>by;
dfs(ax,ay);
if(bj){
cout<<ans;
}
else{
cout<<-1;
}
return 0;
}
byebye~~ <( ̄3 ̄)>