初探深度优先搜索~迷宫问题~从起点出发达到终点的路线个数

问题描述:
某人身处迷宫之中(迷宫可在平面直角坐标系中模拟),他的起始坐标为sx,sy,他要到达fx,fy,已知迷宫中有t处障碍,请你编写一段程序,输出此人欲从起点到达终点的可用路径个数。

输入:
第一行为m,n,t,分别为迷宫的大小(n*m的矩阵),障碍的个数。第二行为sx,sy,fx,fy,分别为此人的起始坐标和终点坐标。之后t行为每行输入两个数据tx,ty,表示障碍的坐标。

输出:
输出此人欲从起点到达终点的可用路径个数。若终点无法到达,输出-1。

样例1:
输入:
2 2 1
1 1 2 2
1 2
输出:
1

数据规模:
2<=n,m<=10.


代码实现:c++
思想:深搜,模拟

#include 
#include 
using namespace std;

const int maxn=10;
bool vis[maxn][maxn]={
     0};
bool bar[maxn][maxn]={
     0};
int n,m,t,sx,sy,fx,fy,cnt=0;
int dir[][2]={
     {
     -1,0},{
     1,0},{
     0,1},{
     0,-1}};/方向数组
void solve(int x,int y)
{
     
	if(x==fx&&y==fy){
     
		cnt++;
		return;
	}	
	
	if(!vis[x][y]||!bar[x][y])	return;
	
	for(int i=0;i<4;i++){
     
		if(x+dir[i][0]<1||x+dir[i][0]>n||y+dir[i][1]<1||y+dir[i][1]>m)	continue;	
		vis[x][y]=false;
		solve(x+dir[i][0],y+dir[i][1]);
		vis[x][y]=true;
	}
}

int main()
{
     
	memset(vis,true,sizeof(vis));//memset初始化bool数组
	memset(bar,true,sizeof(bar));
	cin>>n>>m>>t>>sx>>sy>>fx>>fy;
	for(int i=1;i<=t;i++){
     
		int tx,ty;
		cin>>tx>>ty;
		bar[tx][ty]=false;
	}
	solve(sx,sy);//dfs深搜
	cout<<cnt;
	return 0;
}

代码核心:用于dfs的solve函数

void solve(int x,int y)
{
     
	if(x==fx&&y==fy){
     
		cnt++;
		return;
	}	
	
	if(!vis[x][y]||!bar[x][y])	return;
	
	for(int i=0;i<4;i++){
     
		if(x+dir[i][0]<1||x+dir[i][0]>n||y+dir[i][1]<1||y+dir[i][1]>m)	continue;	
		vis[x][y]=false;
		solve(x+dir[i][0],y+dir[i][1]);
		vis[x][y]=true;
	}
}

以下逐行分析
代码框架:

void solve(int x,int y)
{
     
	//``````
	/*用于搜索的函数一般返回值为空,故用void。
	寻找答案时,在函数外定义全局变量,在函数
	内进行判断,若满足题目条件,输出或改变
	全局变量。*/
	
	//本函数中所需要满足的条件:
	if(x==fx&&y==fy){
     
		cnt++;
		return;
	}	/*x和y代表的是此人当前在平面直角坐标系
	中所处的位置,如果他的位置与终点重合,
	代表他已经到达终点,即他所走过的这条路径
	满足题目条件,用于计数的全局变量cnt
	自增。*/
	if(!vis[x][y]||!bar[x][y])	return;
	/*vis数组用于记录此人所走过的地方,
	显然走回头路是没有意义的,故倘若他重新
	走回他走过的地方,可以直接返回
	(+递归中的返回表示跳出这一层,回到上一层)
	bar数组用于记录障碍物的坐标,显然此人不能
	走到障碍物上是没有意义的,故直接返回。*/
	
	//以上是特判,以下是核心
	for(int i=0;i<4;i++){
     
		if(x+dir[i][0]<1||x+dir[i][0]>n||y+dir[i][1]<1||y+dir[i][1]>m)	continue;	
		//if条件句判断是否越界
		/*dir[][]是方向数组*/
		vis[x][y]=false;
		/*进入下一步之前使vis[x][y]变为false
		,从而使进入下一步之后,不会再重新
		走回这一步上。*/
		//进入下一步,方向数组一个循环使此人有四个方向(上下左右)可选。
		solve(x+dir[i][0],y+dir[i][1]);
		vis[x][y]=true;/*回溯,使这一步变得可用。倘若循环结束,该层solve函数体当中的全部代码都执行完毕了,自动执行return这一步返回上一层,而对上一层来说,这一层的x和y是没有走过的。*/
	}
}

鄙人才疏学浅,代码简陋,讲解过程中难免有不严谨之处,敬请看客谅解!

你可能感兴趣的:(算法学习,c++,dfs)