这是经典的深度优先搜索(DFS)案例。
题目描述:给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
输入:第一行n、m和t,n为行,m为列,t为障碍总数。第二行起点坐标(sx,sy),终点坐标(fx,fy)。接下来t行,每行为障碍点的坐标。
输出:给定起点坐标和终点坐标,问每个方格最多经过1次,从起点坐标到终点坐标的方案总数。
输入输出样例
输入样例
2 2 1
1 1 2 2
1 2
输出样例
1
题目大意:从(sx,sy)点走到(fx,fy)点,其中有 t 处障碍,我们设每个障碍点的坐标为(t1_i,t2_i),求有几条路径。
深度优先搜索(DFS)大体结构:如果已经到了终点,方案数就加1,如果没有到终点,那么就继续搜索
每个方格最多经过1次,他的本意是不能向回走,我们先要建一个二维数组b用来判断(x,y)点有没有走过。
我们走到(x,y)点需要把b[x][y]标记为1(已经走过),搜索完成后,回溯,再把代表(x,y)点有没有走过的b[x][y]标记为0(没有走过)。
如何判断(x,y)点是不是障碍点呢?
我们建一个二维数组a,如果(x,y)点是障碍点,那么就要把 a[x][y] 标记为1,表示(x,y)点是障碍点,不能走;如果(x,y)点不是障碍点,标记为0,表示(x,y)点不是障碍点,可以走。
有了二维数组a和b,就可以解决走没走和障碍点的问题。
那么如何向上下左右移动呢?
我们先看一个例子(如下图):
假设我们在(1,1)点。
向左移动,会移动到(1,0)点,x坐标不变,y坐标减1
向右移动,会移动到(1,2)点,x坐标不变,y坐标加1
向上移动,会移动到(0,1)点,x坐标减1,y坐标不变
向下移动,会移动到(2,1)点,x坐标加1,y坐标不变
所以就得出了dx数组和dy数组(坐标数组)
long long int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
然后用for循环枚举四个方向就行了。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> using namespace std; long long int n,m,t,sx,sy,fx,fy; //n为行,m为列,t为障碍数,sx与sy为起点坐标,fx与fy为终点坐标 long long int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; //方向坐标 long long int ans=0,a[101][101],b[101][101],t1,t2; //ans为方案总数,t1与t2为障碍坐标 //a[i][j]表示地图上的 (i,j) 点是否为障碍,如果是障碍点标记为1,不是障碍点标记为0 //b[i][j]表示地图上的 (i,j) 点是否走过 void dfs(long long int idx,long long int idy) { if(idx==fx&&idy==fy)//是否到达终点 { ans++;//方案数加1 } else//没有到达终点 { for(int i=0;i<4;i++)//枚举四个方向(上下左右) { long long int x=idx+dx[i],y=idy+dy[i]; if((b[x][y]==0&&a[x][y]==0)&&(x>0&&x<=n&&y>0&&y<=m)) //判断 (x,y) 点是否走过,以及是否为障碍,和是否在边界里(不能超出边界) { b[x][y]=1;//标记为1,表示已经走过 dfs(x,y); b[x][y]=0;//回溯,标记为0,表示没有走过 } } } } int main() { scanf("%lld %lld %lld",&n,&m,&t);//输入 scanf("%lld %lld %lld %lld",&sx,&sy,&fx,&fy);//输入起点坐标与终点坐标 b[sx][sy]=1;//每个方格只能走1次,所以也不能回到起点 for(int i=0;i<t;i++) { scanf("%lld %lld",&t1,&t2);//障碍物坐标 a[t1][t2]=1;//标记为1,不可以走 } dfs(sx,sy);//搜索 printf("%lld",ans);//输出方案总数 return 0; }
(第一次写博客,讲的不太详细,请谅解)