迷宫问题,手动模拟栈

1)迷宫问题

①问题描述

这是心理学中的一个经典问题。心理学家把一只老鼠从一个无顶盖的大盒子的入口处放入,让老鼠自行找到出口出来。迷宫中设置很多障碍阻止老鼠前行,迷宫唯一的出口处放有一块奶酪,吸引老鼠找到出口。

简而言之,迷宫问题是解决从布置了许多障碍的通道中寻找出路的问题。本题设置的迷宫如图1所示。

图1 迷宫示意图

迷宫四周设为墙;无填充处,为可通处。设每个点有四个可通方向,分别为东、南、西、北。左上角为入口。右下角为出口。迷宫有一个入口,一个出口。设计程序求解迷宫的一条通路。

②基本要求

  • 设计迷宫的存储结构。

  • 设计通路的存储结构。

  • 设计求解通路的算法。

  • 设计迷宫显示和通路的显示方式。

  • 输入:迷宫、入口及出口可在程序中设定,也可从键盘输入。

  • 输出:迷宫、入口、出口及通路路径。

③实现提示

  • 存储设计

迷宫:以一个m×n的数组表示迷宫,如图3所示。数组元素0和1分别表示迷宫中的通路和障碍。迷宫四周为墙,对应的迷宫数组的边界元素均为1。
























































1

1

1

1

1

1

1

1

1

0

0

1

0

0

0

1

1

1

0

0

0

0

0

1

1

0

0

1

0

1

0

1

1

0

0

0

0

0

0

1

1

1

1

1

1

1

1

1

图2
迷宫存储示意图

方向:每一个可通点有4个可尝试的方向,向不同的方向前进时,目的地的坐标不同。预先把4个方向上的位移存在一个数组中。如把东、南、西、北依次编号为0、1、2、3.其增量数组move[4]如图3所示。






















move[4]

x

y

1

1

0

2

0

1

3

-1

0

4

0

-1

图3
数组move[4]

通路:通路上的每一个点有3个属性:一个横坐标属性x、一个列坐标属性y和一个方向属性d,表示其下一点的位置。如果约定尝试的顺序为东、南、西、北,则每尝试一个方向不通时,d值增1,当d增至4时,表示此位置一定不是通路上的点,从栈中去除。在找到出口时,栈中保存的就是一条迷宫通路。

  • 算法设计

要寻找一条通过迷宫的路径,就必须进行试探性搜索,只要有路可走就前进一步,无路可进,换一个方向进行尝试;当所有方向均不可走时,则沿原路退回一步,重新选择未走过可走的路,如此继续,直至到达出口或返回入口(没有通路)。在探索前进路径时,需要将搜索的踪迹记录下来,以便走不通时,可沿原路返回到前一个点换一个方向再进行新的探索。后退的尝试路径与前进路径正好相反,因此可以借用一个栈来记录前进路径。

寻找通路的算法思想如下:

Setp1:入口点坐标及到达该点方向(设为-1)入栈。

Step2:当栈不空时循环执行下列操作:

2.1 栈顶元素出栈至(x,y,d)。

2.2 按预设定顺序求出下一个要试探的方向d++,执行下述操作:

2.2.1 如果方向d可走,则:

2.2.1.1 将(x,y,d)入栈。

2.2.1.2 求新点坐标,得新(x,y)。

2.2.1.3
如果新点(x,y)是终点,则试探结束;
否则,置d=0。

2.2.2否则,试探下一个方向,d++。

Setp3:栈空,表示没有通路;否则,出栈,得到通路路径。

④测试与运行

  • 当迷宫数组为图3所示时,(1,1)为入口,(4,6)为出口,则可能的通路为:
    通路1:(1,1)、(1,2)、(2,2)、(3,2)、(4,2)、(4,3)、(4,4)、(4,5)、(4,6)
    通路2:(1,1)、(1,2)、(2,2)、(2,3)、(2,4)、(3,4)、(4,4)、(4,5)、(4,6)
    通路3:(1,1)、(1,2)、(2,2)、(2,3)、(2,4)、(2,5)、(2,6)、(3,6)、(4,6)

  • 重设迷宫,使得没有通路,进行测试。

⑤思考

    • 若每个点有8个试探方向(东、东南、南、西南、西、西北、北、东北),如何修改程序?

    • 如何求得所有通路?

    • 如何求得最短通路?

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

#include<iostream>

#include<string.h>

#include<cstdio>

using
namespace std;

class
Stack

{

public:

    struct
Node//栈里有三个变量和一个指针

    {

        int
x;

        int
y;

        int
d;//方向

        Node * next;

        Node():next(NULL) {}

        Node(int
a,int b,int c):x(a),y(b),d(c),next(NULL) {}

    };

    int
length;

    Node * topOfStack;//栈顶指针

    Stack(int
a,int b ,int
c)//构造函数 赋值

    {

        int
length = 1;

        Node * p = new
Node(a,b,c);

        topOfStack = p;

    }

    void
push(int 
a,int 
b,int 
c)//入栈

    {

        Node * p = new
Node(a,b,c);

        p -> next = topOfStack;

        topOfStack = p;

        length ++;

    }

    void
pop()//出栈

    {

        Node * p = topOfStack -> next;

        delete
topOfStack;

        topOfStack = p;

        length --;

    }

    void
print()//打印

    {

        Node * p = topOfStack;

        while(p !=NULL)

        {

            cout<<"("<<p->x<<","<<p->y<<")"<<endl;

            cout<<"↑"<<endl;

            p = p -> next;

        }

    }

    bool
isEmpty()//判断是不是空栈

    {

        if(topOfStack == NULL)return
true;

        else
return false;

    }

    void
Clear()//删除栈中元素

    {

        while(!isEmpty())

        {

            Node * p = topOfStack;

            topOfStack = topOfStack -> next;

            delete
p;

            p = topOfStack;

        }

    }

};

int
main()

{

    //freopen("in.cpp","r",stdin);

    cout<<"please input m and n"<<endl;

    int
m,n;

    while(cin>>m>>n)

    {

        int
Map[m][n];

        int
road[m][n];//记录该节点是否被访问,0代表没访问过,1代表访问过

        for(int
i = 0 ; i < m ; i++)

        {

            for( int
j = 0 ; j < n ; j++)

            {

                cin>>Map[i][j];

            }

        }

        memset(road,0,sizeof(road));//对road清零处理

        cout<<"entrance:"<<endl;

        int
entr[1][2];//入口坐标

        cin>>entr[0][0]>>entr[0][1];

        cout<<"exit:"<<endl;

        int
exit[1][2];//出口坐标

        cin>>exit[0][0]>>exit[0][1];

        int
d[6]= {0,1,2,3,4,5}; //1左 2下 3右 4上

        if((Map[entr[0][0]][entr[0][1]]==1)||(Map[exit[0][0]][exit[0][1]]==1))

        {

            cout<<"input error"<<endl;

            continue;

        }

        Stack dusk(entr[0][0],entr[0][1],d[1]);//把入口坐标和方向1压入栈

        road[entr[0][0]][entr[0][1]]=1;//入口坐标被访问

        while((dusk.topOfStack->x != exit[0][0])||(dusk.topOfStack->y != exit[0][1]))

            //当入口坐标和出口坐标的x,y有一个不一样就循环

        {

            if(dusk.topOfStack->d == d[1])//方向1

            {

                if(Map[dusk.topOfStack->x][dusk.topOfStack->y-1] == 0

                        && dusk.topOfStack->x>=0

                        && dusk.topOfStack->x<=m

                        &&dusk.topOfStack->y-1>=0

                        &&dusk.topOfStack->y-1<=n

                        &&road[dusk.topOfStack->x][dusk.topOfStack->y-1]==0)

                    //满足左边的节点没被访问、值为0、在n*m内,就把左边的节点压入栈

                {

                    dusk.push(dusk.topOfStack->x,dusk.topOfStack->y-1,d[1]);

                    road[dusk.topOfStack->x][dusk.topOfStack->y]=1;

                }

                else

                {

                    //如果不满足,方向+1

                    dusk.topOfStack->d ++;

                }

            }

            if(dusk.topOfStack->d == 2)

            {

                if(Map[dusk.topOfStack->x+1 ][dusk.topOfStack->y] == 0

                        && dusk.topOfStack->x+1>=0 && dusk.topOfStack->x+1<=m

                        &&dusk.topOfStack->y>=0&&dusk.topOfStack->y<=n

                        &&road[dusk.topOfStack->x+1][dusk.topOfStack->y]==0

                  )

                {

                    dusk.push(dusk.topOfStack->x+1,dusk.topOfStack->y,d[1]);

                    road[dusk.topOfStack->x][dusk.topOfStack->y]=1;

                }

                else

                {

                    dusk.topOfStack->d ++;

                }

            }

            if(dusk.topOfStack->d == 3)

            {

                if(Map[dusk.topOfStack->x][dusk.topOfStack->y+1] == 0

                        && dusk.topOfStack->x>=0 && dusk.topOfStack->x<=m

                        &&dusk.topOfStack->y+1>=0&&dusk.topOfStack->y+1<=n

                        &&road[dusk.topOfStack->x][dusk.topOfStack->y+1]==0)

                {

                    dusk.push(dusk.topOfStack->x,dusk.topOfStack->y+1,d[1]);

                    road[dusk.topOfStack->x][dusk.topOfStack->y]=1;

                }

                else

                {

                    dusk.topOfStack->d ++;

                }

            }

            if(dusk.topOfStack->d == 4)

            {

                if(Map[dusk.topOfStack->x-1][dusk.topOfStack->y] == 0

                        && dusk.topOfStack->x-1>=0 && dusk.topOfStack->x-1<=m

                        &&dusk.topOfStack->y>=0&&dusk.topOfStack->y<=n

                        &&road[dusk.topOfStack->x-1][dusk.topOfStack->y]==0)

                {

                    dusk.push(dusk.topOfStack->x-1,dusk.topOfStack->y,d[1]);

                    road[dusk.topOfStack->x][dusk.topOfStack->y]=1;

                }

                else

                {

                    dusk.topOfStack->d ++;

                }

            }

            if(dusk.topOfStack->d == 5)//如果四个方向都走不通,就出栈

            {

                dusk.pop();

            }

            if(dusk.topOfStack==NULL)//如果到不了

            {

                cout<<"can not arrive"<<endl;

                break;

            }

        }

        dusk.print();//打印

        dusk.Clear();//初始化

        cout<<"please input m and n"<<endl;

    }

}

  

迷宫问题,手动模拟栈,布布扣,bubuko.com

时间: 2024-10-27 13:15:33

迷宫问题,手动模拟栈的相关文章

51单片机的仿真栈(模拟栈/可重入栈)

51单片机的仿真栈(又叫模拟栈.或者可重入栈). 首先来看,51的系统栈(又叫系统栈,或者硬件栈),就是SP所指向的栈,他是一个满增栈(注释1),位于片内RAM的128 bytes之中,上电之后系统堆栈指针SP的初值等于多少呢?这个要从51的启动文件来分析,启动文件中有这样的汇编代码: ?STACK SEGMENT IDATA ;定义一个片内数据段,段名:?STACK RSEG ?STACK ;选择之前定义过的一个可重定位的段?STACK,下面的汇编语句将会被放置到该段,直到遇到下一个段定位指令

java 16 - 5 LinkedList模拟栈数据结构的集合

请用LinkedList模拟栈数据结构的集合,并测试 题目的意思是: 你自己的定义一个集合类,在这个集合类内部可以使用LinkedList模拟. 1 package cn_LinkedList; 2 3 import java.util.LinkedList; 4 5 6 7 8 public class MyStack { 9 10 //定义一个LinkedList类的成员变量 11 private LinkedList list = null; 12 13 /** 14 * 构造方法 15

Hdu 3887树状数组+模拟栈

题目链接 Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1757    Accepted Submission(s): 582 Problem Description You are given a tree, it’s root is p, and the node is numbered fr

用数组模拟栈的结构

package datastruct; import java.util.Arrays; /** * 用数组模拟栈的结构:后进先出(LIFO) 线性表结构 * @author stone * 2014-07-29 06:34:49 */ public class SimulateStack<E> { public static void main(String[] args) { SimulateStack<String> ss = new SimulateStack<Str

手动模拟获取latch

随意dump一个latches结构文件: SQL> oradebug dump latches 10 ORA-00074: no process has been specified SQL> oradebug setmypid Statement processed. SQL> oradebug dump latches 10 Statement processed. SQL> oradebug tracefile_name /oracle/diag/rdbms/orcl/orc

采用LinkedList来模拟栈数据结构的集合--先进后出

三.用LinkedList来模拟栈数据结构的集合 /* * 自定义一个数据结构为LinkedList的集合类*/public class MyCollection_LinkedList { public LinkedList linkedList;            public MyCollection_LinkedList() {             //在构造方法里初始化             linkedList= new LinkedList();             }

【手动开栈】【dfs序】【树状数组】【Tarjan】bzoj2819 Nim

考虑树状数组区间修改(只对其子树的答案有影响)点查询,每个点记录的是它到根路径上的权值异或和. 答案时query(L)^query(R)^a[lca]. 这种方法在支持区间加法.减法的树上询问的时候可以避免树链剖分. 可能爆栈,考虑手动开栈.(诶诶Tarjan预处理lca的时候怎么没手动开栈?不要在意^_^) 实际上不会爆的. #include<cstdio> #include<stack> #include<algorithm> #include<queue&g

java、C语言实现数组模拟栈

java: public class ArrayStack { private int[] data; private int top; private int size; public ArrayStack(int size) { this.data = new int[size]; this.size = size; this.top = -1; } public boolean isEmpty() { if (this.top == -1) { return true; } return

[欧拉回路+手动开栈] poj 1780 Code

题目链接: http://poj.org/problem?id=1780 Code Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2037   Accepted: 751 Description KEY Inc., the leading company in security hardware, has developed a new kind of safe. To unlock it, you don't need