深度优先搜索(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行代码处应该好好理解一下,注释有提出

 
posted @ 2017-03-07 10:57  小小范同学  阅读(1418)  评论(0编辑  收藏  举报