p1605 迷宫 题解

· · 个人记录

题目链接:https://www.luogu.com.cn/problem/P1605

首先,这是一道非常经典的题。这道题首先dfs,即深度优先搜索解题。因为题目问的是有多少种方法可以到达终点,所以采用dfs,若是问最佳的路径,则用bfs。

言归正传,这道题怎么做呢?

一、地图的储存

有一些同学开了两个数组,分别存放地图和走过标记,其实这样太麻烦了。因为走过和不能走(有障碍),都是同一种状态:走不了,所以,我们不妨只开一个数组,用这个数组存放走过和没有走过的标记。其中false表示没有走过,我们在程序的开始可以用memset把这个数组刷0,然后循环输入障碍的坐标,把这些坐标在数组中标位true,表示不能走。

二、搜索

首先我们要搞清楚搜索的状态。到达终点是最终的想要的状态,所以如果当前的坐标和终点坐标相同,那么就将sum(总和)的值+1,然后return继续搜索(因为递归使用栈来储存的,所以return之后,会回到上一层,也就是上一次的坐标状态)。

其次,我们要知道怎么在地图上进行运动。这个时候就需要用到屠龙刀——方向数组了。定义两个数组dx和dy,表示x和y的移动规律,因为题目要求朝上、下、左、右四个方向移动,所以数组大小为4。

在没有到达最终状态的时候,我们可以用一个for循环来控制坐标在图上移动。在落下移动之前要判断能否到达这个点:

1、这个点是false,即没有走过或不是障碍 2、这个点在n*m的范围内

最后进行深度优先搜索,将落下的这个点标位true(已经走过),然后继续搜索,在搜索到达return之后,把刚在落下的这个点,重新标为未走过。

代码:

#include<bits/stdc++.h> 
using namespace std;
int m,n,t,sx,sy,fx,fy,sum;
int dx[4]={0,0,1,-1}, 
    dy[4]={-1,1,0,0};
bool visited[100][6];
bool can(int x,int y)
{
    bool b=true;
    b=(x<=n)&&(y<=m);
    b=b & ((x>=1) && (y>=1));
    return b;
}
void dfs(int x,int y)
{
    if(x==fx && y==fy)
    {///到达终点  
        sum++;
        return;
    }
    else
    {
        for(int i=0;i<=3;i++)
        {///搜索方向  
            if(visited[x+dx[i]][y+dy[i]]==0 && can(x,y))
            {///没有走过或可以走(即不为障碍)   
                visited[x][y]=1;  ///标记为走过 
                dfs(x+dx[i],y+dy[i]); ///进一步由下一步搜索  
                visited[x][y]=0;  ///回溯  
            }
        }
    }
}
int main()
{
    cin>>n>>m>>t;
    cin>>sx>>sy>>fx>>fy;
    memset(visited,0,sizeof(visited));///全部标位未走过 false  
    for(int i=1;i<=t;i++)
    {///在map中只有两个状态,要么走过,要么未走过,
     ///因为走过之后就不能走了,所以他的状态和不能走是一样的,所以都用同一种方法表示  
        int x,y;
        cin>>x>>y;
        visited[x][y]=1;  ///不能走的位置就是已经走过的位置 标位已走过 true  
    }
    dfs(sx,sy);
    cout<<sum<<endl;
    return 0;
}