今天,寒假第2天。
今天看的是栈与队列。课本上关于栈,列举了一些应用实例。其中一个就是关于迷宫出口的搜索问题。想起之前在刘汝佳的《算法竞赛入门经典》上的关于这个问题的深度优先方法。通过深度优先方法,可以求出最短的走出迷宫的路径,其基本思想是:将整个迷宫地图视为一棵二叉树,其中在迷宫中先走到的地方视为它所能及地方的双亲节点,于是:迷宫的起始点可视为根节点,与迷宫一步之遥的所有节点都可视为根节点的孩子节点,与孩子节点一步之遥的又可视为孩子的孩子节点...依此类推。当然,我们还需要一个数组记录已经走过的节点,这些节点是不需再走第二次的,如果经过这些节点能到达终点,走一次就够了,何况先前“抢占”该节点的路径一定能更先到达终点。
如果利用栈的方式,则是“一条路走到黑”,要么走到了终点,要么走到死胡同再折返回来。这种方式同样需要记录已走过的节点,以免浪费不必要的时间。
这两种方法实现起来都不太难,基本思路就是BFS(广度优先)和DFS(深度优先)的基本思路。关于最后输出的问题,如果用DFS,只需用一个数组,走一步标记一下,返一步在标记回来,这样最后就能得到结果了;如果用BFS会稍微复杂一些,因为这种方式是“齐头并进”,大家一起一步一步往前走,很难做标记。因此在走的过程中,要用一个数组,能体现出后面经过的节点与它之前节点之间的关系,一种具体方法是:在arr[x][y]中存放走到坐标(x,y)的前一步的坐标。这样顺着出口往回找,最终一定能找到入口。
运行结果如下:(图一)基于栈的DFS,(图二)基于队列的BFS。两者结果不同,其中BFS的是最短路径。
1 /*
2 功能:
3 使用栈,实现对于迷宫的广度优先搜索。
4 输入:
5 无
6 输出:
7 迷宫图形
8 FINISHED DATE:
9 2013.1.13
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 //define size value
15 #define MAXWIDTH 5
16 #define MAXLENGTH 8
17 #define STACKSIZE 100
18 //define return value
19 #define ERROR 0
20 #define OK 1
21 #define OVERFLOW 0
22 typedef struct {
23 int x,y;
24 }Pos;
25 typedef struct {
26 Pos *base,*top;
27 int stack_size;
28 }Stack;
29 bool StackEmpty(Stack s) {
30 return (s.top == s.base);
31 }
32 int StackPop(Stack &s,Pos &p,bool isPop)
33 {
34 if(s.base == s.top)
35 return ERROR;
36 p.x = (s.top-1)->x;
37 p.y = (s.top-1)->y;
38 if(isPop) s.top--;
39 return OK;
40 }
41 int StackPush(Stack &s,Pos p)
42 {
43 if(s.top-s.base >= s.stack_size)
44 return ERROR;
45 s.top->x = p.x;
46 s.top->y = p.y;
47 s.top++;
48 return OK;
49 }
50 int InitStack(Stack &s)
51 {
52 s.base = s.top = (Pos *)malloc(sizeof(Pos)*STACKSIZE);
53 if(!s.base) return OVERFLOW;
54 s.stack_size = STACKSIZE;
55 return OK;
56 }
57 void FindPath(int Maze[MAXWIDTH][MAXLENGTH],Pos des)
58 {
59 Stack s;Pos pos;
60 int footprint[MAXWIDTH][MAXLENGTH]={0},res[MAXWIDTH][MAXLENGTH]={0};
61 InitStack(s);
62 pos.x = pos.y = 0;//起始点为(0,0)
63 StackPush(s,pos);
64 footprint[0][0] = res[0][0] = 1;
65 while(!StackEmpty(s)) {
66 StackPop(s,pos,false);
67 if(pos.x == des.x && pos.y == des.y)
68 break;
69 if(pos.y+1 < MAXLENGTH && !footprint[pos.x][pos.y+1] && !Maze[pos.x][pos.y+1]) {
70 footprint[pos.x][pos.y+1] = res[pos.x][pos.y+1] = 1;
71 pos.y++;
72 StackPush(s,pos);
73 }
74 else if(pos.x+1 < MAXWIDTH && !footprint[pos.x+1][pos.y] && !Maze[pos.x+1][pos.y]) {
75 footprint[pos.x+1][pos.y] =res[pos.x+1][pos.y] = 1;
76 pos.x++;
77 StackPush(s,pos);
78 }
79 else if(pos.y-1 >= 0 && !footprint[pos.x][pos.y-1] && !Maze[pos.x][pos.y-1]) {
80 footprint[pos.x][pos.y-1] = res[pos.x][pos.y-1] = 1;
81 pos.y--;
82 StackPush(s,pos);
83 }
84 else if(pos.x-1 >= 0 && !footprint[pos.x-1][pos.y] && !Maze[pos.x-1][pos.y]) {
85 footprint[pos.x-1][pos.y] = res[pos.x-1][pos.y] = 1;
86 pos.x--;
87 StackPush(s,pos);
88 }
89 else {
90 StackPop(s,pos,true);
91 res[pos.x][pos.y] = 0;
92 }
93 }
94 if(!StackEmpty(s)) {
95 //have found the path
96 printf(" ");
97 for(int j = 0;j<MAXLENGTH;++j)
98 printf("%d ",j);
99 printf("\n");
100 for(int i = 0;i<MAXWIDTH;++i) {
101 printf("%d ",i);
102 for(int j = 0;j<MAXLENGTH;++j) {
103 if(res[i][j]) {
104 printf("※");
105 }
106 else if(Maze[i][j]) printf("■");
107 else printf(" ");
108 }
109 printf("\n");
110 }
111 }
112 else printf("No path found!\n");
113 }
114 int main()
115 {
116 int Maze[MAXWIDTH][MAXLENGTH] = {{0,0,0,0,1,1,1,0},{0,1,0,1,0,0,0,0},{0,1,0,0,0,1,1,0},{0,0,0,1,1,1,0,0},{1,1,0,0,0,0,0,0}};
117 Pos des;
118 des.x = 4;des.y = 7;
119 FindPath(Maze,des);
120 system("pause");
121 return 0;
122 }
1 /*
2 功能:
3 使用队列,实现对于迷宫的深度优先搜索。找到最短路径。
4 输入:
5 无
6 输出:
7 迷宫图形
8 FINISHED DATE:
9 2013.1.13
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 //define size value
15 #define MAXWIDTH 5
16 #define MAXLENGTH 8
17 #define MAXSIZE 5000
18 //define return value
19 #define ERROR 0
20 #define OK 1
21 #define OVERFLOW 0
22 typedef struct {
23 int x,y;
24 }Pos;
25 typedef struct {
26 Pos *base;
27 int front,rear;
28 int queue_size;
29 }Queue;
30 int InitQueue(Queue &q)
31 {
32 q.base = (Pos*)malloc(sizeof(Pos)*MAXSIZE);
33 q.front = q.rear = 0;
34 q.queue_size = MAXSIZE;
35 return OK;
36 }
37 int QueuePush(Queue &q,Pos pos)
38 {
39 //Queue is full
40 if((q.rear+1)%q.queue_size==q.front) {
41 return ERROR;
42 }
43 q.base[q.rear].x = pos.x;
44 q.base[q.rear].y = pos.y;
45 q.rear = (q.rear+1)%q.queue_size;
46 return OK;
47 }
48 int QueuePop(Queue &q,Pos &pos,bool isPop)
49 {
50 //queue is empty
51 if(q.front==q.rear) {
52 return ERROR;
53 }
54 pos.x = q.base[q.front].x;
55 pos.y = q.base[q.front].y;
56 if(isPop) q.front = (q.front+1)%q.queue_size;
57 return OK;
58 }
59 bool QueueEmpty(Queue q)
60 {
61 return (q.rear==q.front);
62 }
63 void FindPath(int Maze[MAXWIDTH][MAXLENGTH],Pos des)
64 {
65 Queue q;Pos pos,tmp;
66 int footprint[MAXWIDTH][MAXLENGTH]={0};
67 Pos res[MAXWIDTH][MAXLENGTH];
68 InitQueue(q);
69 pos.x = 0;pos.y = 0;
70 QueuePush(q,pos);
71 while(!QueueEmpty(q)){
72 QueuePop(q,pos,1);
73 if(pos.x == des.x && pos.y == des.y)
74 break;
75 if(pos.y+1 < MAXLENGTH && !footprint[pos.x][pos.y+1] && !Maze[pos.x][pos.y+1]) {
76 footprint[pos.x][pos.y+1] = 1;
77 res[pos.x][pos.y+1].x = pos.x;
78 res[pos.x][pos.y+1].y = pos.y;
79 tmp.x = pos.x;
80 tmp.y = pos.y+1;
81 QueuePush(q,tmp);
82 }
83 if(pos.x+1 < MAXWIDTH && !footprint[pos.x+1][pos.y] && !Maze[pos.x+1][pos.y]) {
84 footprint[pos.x+1][pos.y] = 1;
85 res[pos.x+1][pos.y].x = pos.x;
86 res[pos.x+1][pos.y].y = pos.y;
87 tmp.x = pos.x+1;
88 tmp.y = pos.y;
89 QueuePush(q,tmp);
90 }
91 if(pos.y-1 >= 0 && !footprint[pos.x][pos.y-1] && !Maze[pos.x][pos.y-1]) {
92 footprint[pos.x][pos.y-1] = 1;
93 res[pos.x][pos.y-1].x = pos.x;
94 res[pos.x][pos.y-1].y = pos.y;
95 tmp.x = pos.x;
96 tmp.y = pos.y-1;
97 QueuePush(q,tmp);
98 }
99 if(pos.x-1 >= 0 && !footprint[pos.x-1][pos.y] && !Maze[pos.x-1][pos.y]) {
100 footprint[pos.x-1][pos.y] = 1;
101 res[pos.x-1][pos.y].x = pos.x;
102 res[pos.x-1][pos.y].y = pos.y;
103 tmp.x = pos.x-1;
104 tmp.y = pos.y;
105 QueuePush(q,tmp);
106 }
107 }
108 if(!QueueEmpty(q)) {
109 //have found the path
110 int x,y,tx;
111 x = des.x;
112 y = des.y;
113 memset(footprint,0,MAXWIDTH*MAXLENGTH*sizeof(int));
114 while(x!=0||y!=0) {
115 footprint[x][y] = 1;
116 tx = res[x][y].x;
117 y = res[x][y].y;
118 x = tx;
119 }
120 footprint[x][y] = 1;
121 printf(" ");
122 for(int j = 0;j<MAXLENGTH;++j)
123 printf("%d ",j);
124 printf("\n");
125 for(int i = 0;i<MAXWIDTH;++i) {
126 printf("%d ",i);
127 for(int j = 0;j<MAXLENGTH;++j) {
128 if(footprint[i][j]) {
129 printf("※");
130 }
131 else if(Maze[i][j]) printf("■");
132 else printf(" ");
133 }
134 printf("\n");
135 }
136 }
137 else printf("No path found!\n");
138
139 }
140 int main()
141 {
142 int Maze[MAXWIDTH][MAXLENGTH] = {{0,0,0,0,1,1,1,0},{0,1,0,1,0,0,0,0},{0,1,0,0,0,1,1,0},{0,0,0,1,1,1,0,0},{1,1,0,0,0,0,0,0}};
143 Pos des;
144 des.x = 4;des.y = 7;
145 FindPath(Maze,des);
146 system("pause");
147 return 0;
148 }