题目分类:回溯算法(dfs)


\(\color{#0000FF}{*回溯算法*}\)实际上是一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。

——百度百科


P1605 迷宫



题目背景

给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

输入格式

第一行N、M和T,N为行,M为列,T为障碍总数。第二行起点坐标SX,SY,终点坐标FX,FY。接下来T行,每行为障碍点的坐标。

输出格式

给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。


//

说明/提示
【数据规模】

1≤N,M≤5


我的想法

蒟蒻乐乐昨晚睡觉前看了b站阿婆主回溯算法的讲解,这才发现这道题用回溯算法是好做的。
不过提交了三次才ac:
第一次的wa是因为直接令终点在上下左右的时候就return,没有考虑到靠近了终点仍绕行的情况;
第二次就是因为题目的坑,最后把检测点下载下来才发现我的代码没有排除障碍物直接设在终点的情况——即障碍物若设在终点,那么怎样也无法到达,应该返回0;
最后将障碍物的初始化放在终点的初始化后面,才得以ac。。太坑了鸭。。

下面是小蒟蒻乐乐的代码


我的代码:

#include
using namespace std;
int a[7][7];
int xx[4]={1,0,0,-1},yy[4]={0,1,-1,0};
int cnt=0;
int end(int x,int y) 
{
	if(a[x][y]==5000)
	return 1;
	if(a[x][y+1]==5&&a[x][y-1]==5&&a[x-1][y]==5&&a[x+1][y]==5)
	return 0;
	else
	return 2;	
}
void dfs(int x,int y)
{
	int e=end(x,y);
	if(e==1){cnt++;return;}
	if(e==0){return;}
	for(int i=0;i<4;i++)
	{
		if(a[x+xx[i]][y+yy[i]]==0||a[x+xx[i]][y+yy[i]]==5000)
		{
			a[x][y]=5;
			dfs(x+xx[i],y+yy[i]);
			a[x][y]=0;	
		}
		
	}
	
}
int main()
{
	int N,M,T,sx,sy,fx,fy;
	cin>>N>>M>>T>>sx>>sy>>fx>>fy;
	
	//画好边框 
	for(int i=1;i<=N;i++)
	{
		a[i][0]=5;
		a[i][M+1]=5;
	}
	for(int i=1;i<=M;i++)
	{
		a[0][i]=5;
		a[N+1][i]=5;
	}
	//终点放上珍宝
	a[fx][fy]=5000;
	//设置障碍 
	for(int i=0;i>x>>y;
		a[x][y]=5;
	}
	dfs(sx,sy);
	cout<