• P1605 迷宫


    luogu P1605 迷宫

     这是经典的深度优先搜索(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;
    }

    (第一次写博客,讲的不太详细,请谅解)

  • 相关阅读:
    剑指offer思路总结
    redis为什么设计成单线程
    vscode 常用工具
    redis 数据结构的实现
    记一次rm -rf 的悲伤故事
    netstate端口连接状态
    查询mysql最后更新时间
    boost库安装
    docker镜像不支持常用命令
    消息队列--线程安全
  • 原文地址:https://www.cnblogs.com/wswxx/p/13287062.html
Copyright © 2020-2023  润新知