zoukankan      html  css  js  c++  java
  • 深度优先搜索(DFS),逃离迷宫

    【原创】

    今天来说说深度优先搜索,深度优先是图论中的内容,大意是从某一点出发,沿着一个方向搜索下去,并伴随着有回退的特点,通常用来判断某一解是否存在,不用来寻找最优解;这里来看一个非常有意思的题目;

    题目描述:一只小狗在迷宫中,假设在迷宫用字符表示,如图所示:

    S.X.
    ..X.
    ...D

    这其中,S表示起点,是需要程序寻找出来的,这里比较特殊,在最左上角,“.”表示可走的格子,D表示出口,X表示强,不能走,每一秒小狗必须移动一个距离,即前后左右,那么输入时间t,小狗能否刚好在t秒的时间上到达D,看清楚是刚好在t秒上,不是至少在t秒内,所以程序中的判断应该注意这一点,
    思想:利用深度优先搜索,将每一个点的状态抽象出来,一个三元组(x,y,t);x,y代表坐标,t表示从起点到这一坐标的时间,那么这就是一个状态,深度搜索的任务就是对状态的扩展,观察并判断是否到达目标状态;见如下代码,注释地方都有,同时支持多组测试数据;
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 //深度优先搜索
     5 //小狗逃离迷宫问题
     6 char maze[8][8];//输入的迷宫规模1 < n < 7
     7 int nd,md,t;//nd和md表示是矩阵迷宫的规模,t为时间,nd表示x方向,md表示y方向
     8 bool success;//标记
     9 int go[][2] = {1,0,-1,0,0,1,0,-1};//一个点可以扩展的上下左右四个状态
    10 void DFS(int x,int y,int time){
    11     for (int i = 0; i<4; i++) {//对这个点进行四个方向的扩展
    12         int nx = x+go[i][0];
    13         int ny = y+go[i][1];
    14         if (nx<1||nx>nd||ny<1||ny>md) continue;//表示跳出了迷宫
    15         if(maze[nx][ny]=='X')continue;//该位置为墙
    16         if(maze[nx][ny]=='D'){//找到了出口,
    17             if(time+1==t){//由于题目要求的是t时间刚好到达出口,所以这里不能用<t作为判断;
    18                 success = true;
    19                 return;
    20             }
    21             else
    22                 continue;//继续,并且该状态的后继状态不可能为答案,
    23         }
    24         maze[nx][ny] = 'X';//说明这个状态能够扩展,之所以将其修改为墙,是因为防止后继状态又扩展回这个状态
    25         DFS(nx, ny, time+1);// 继续从该状态扩展
    26         maze[nx][ny] = '.';//返回后要将其修改回原来的状态
    27         if(success)return;//说明找到了目标状态且满足题意,可以返回;
    28     }
    29 }
    30 void test_3(){
    31     while (scanf("%d%d%d",&nd,&md,&t)!=EOF) {
    32         if (nd==0&&md==0&&t==0) break;
    33         for (int i = 1; i<=nd;i++) {
    34             scanf("%s",maze[i]+1);//输入字符迷宫,必须+1,这才是从[1][1]开始的
    35         }
    36         success = false;
    37         for (int i = 1;i<=nd;i++) {//寻找开始坐标
    38             for (int j = 1; j<=md; j++) {
    39                 if(maze[i][j]=='S'){
    40                     maze[i][j] = 'X';//将起点标记为墙
    41                     DFS(i,j,0);//开始扩展;
    42                     break;
    43                 }
    44             }
    45         }
    46         puts(success==true?"YES":"NO");
    47          
    48     }
    49 }
    50 int main() {
    51 //    test_1();
    52 //    test_2();
    53     test_3();
    54     return 0;
    55 }
    56  
    57 /**************************************************************
    58     Problem: 1461
    59     User: Numen_fan
    60     Language: C++
    61     Result: Accepted
    62     Time:10 ms
    63     Memory:1020 kb
    64 ****************************************************************/

    注:迷宫输入一定是从maze[1][1],开始的,因此34行处scanf("%s",maze[i]+1);还有就是24-16行代码处应该好好理解一下,注释有提出

     
  • 相关阅读:
    PHP新建文件并写入内容demo
    PHP输出结果demo
    网站顶部图标使用分析
    .htaccess文件的创建 / 联动天下空间伪静态(isapi_rewrite)配置方法
    【原创】网站底部竖线布局对比/研究
    JS判断访问设备终端PC/iPad/iPhone/android 和浏览器IE/Opera/Firefox/webKit
    我的blog风格
    2020.11.17 近日复健情况
    南风又起,锦字题予往昔(写给校刊《我们大多数》)
    【对拍大法好!!】
  • 原文地址:https://www.cnblogs.com/numen-fan/p/6513602.html
Copyright © 2011-2022 走看看