C語言實驗:迷宮問題(搜索,C語言實現棧、隊列)


Description

給定迷宮起點和終點,尋找一條從起點到終點的路徑

 

 

(0,1)

 

 

 

 

(2,0)

起點

(1,1)

(1,2)

(1,3)

(1,4)

 

(2,0)

(2,1)

 

 

(2,4)

 

(3,0)

(3,1)

(3,2)

 

終點

3,4

 

 

(4,1)

 

 

 

 

 

上圖中黃色代表牆,白色代表通路,起點為(1,1),終點為(3,4)

要求搜尋策略是從起點開始按照“上、下、左、右四個方向尋找終點,到下一個點繼續按照上、下、左、右四個方面尋找,當該結點四個方向都搜尋完,但還沒到終點時,退回到上一個點,直到找到終點或者沒有路徑。

比如上圖從(1,1)開始,向上(0,1)不通,向下到(2,1);到了(2,1)后繼續按上、下、左、右四個方面尋找,上已經走過,向下到(3,1);到(3,1)后上已經走過,下和左不通,向右到(3,2);到(3,2)四個方面都不通,回到(3,1)四個方向都不通,再回到(2,1),(1,1);到達(1,1)后下已經走過,左不通,繼續向右走,重復這個過程最后到達(3,4)

Input

第一行兩個數mn表示迷宮的行數和列數。迷宮大小不超過100×100

第二行四個數x1,y1,x2,y2分別表示起點和終點的坐標。

接下來是mn列的數,用來表示迷宮,1表示牆,0表示通路。

Output

從起點到終點所經過的路徑的坐標。如果不存在這樣的路徑則輸出“No Path!

Sample Input

5 6
1 1 3 4
1 1 1 1 1 1 
1 0 0 0 0 1 
1 0 1 1 0 1
1 0 0 1 0 1
1 1 1 1 1 1

Sample Output

(1 1)(1 2)(1 3)(1 4)(2 4)(3 4)


1.思路:
1)若當前點是終點,dfs函數返回1;
2)若不是終點,將此點標記為1,對該點4個方向進行搜索,實現方式為定義int  dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 通過一個小循環:

  for(int i = 0; i < 4; i++) { 
    position nextp;  
nextp.x = dir[i][0] + now.x;
nextp.y = dir[i][1] + now.y;
......
  } 
進行搜索;若該點的下一個點nextp不是牆,未走,並且沒有超界則將nextp壓入棧中,遞歸調用dfs,若此過程經過(1)判斷返回了1,說明最終找到了通往終點的路,便可以返回1,結束函數,此時棧中已儲存了通往終點的路徑,
若沒有通路,則彈出棧頂元素,根據遞歸原理該路徑上的所有點都會彈出並標記未走,回溯到之前的點,繼續向其他方向搜索,直到找到終點或遍歷完整個圖。
(3)遍歷整個圖都沒有發現通往終點的路,則輸出“No Path!”。

 

2.代碼:
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <math.h>
 5 
 6 typedef struct {
 7     int x;
 8     int y;
 9 }position;
10 
11 typedef struct my_stack {
12     int len;
13     position path[10001];//用數組表示棧內元素
14 }Stack;
15 
16 
17 /*棧的實現*/
18 Stack *create_emptystack();
19 int isempty(Stack *s);
20 void push_stack(Stack *s, position pos);
21 void pop_stack(Stack *s);
22 //position get_top(Stack *s);
23 
24 /*dfs*/
25 int judge(position p);
26 int dfs(Stack *s, position now);
27 
28 int a[100][100];
29 position begin, end;
30 int m, n;
31 
32 int main() {
33     scanf("%d%d", &m, &n);
34     scanf("%d%d%d%d", &begin.x, &begin.y, &end.x, &end.y);
35     for(int i = 0; i < m; i++) {
36         for(int j = 0; j < n; j++)
37             scanf("%d", &a[i][j]);
38     }
39     Stack *s = create_emptystack();
40     push_stack(s, begin);
41     dfs(s, begin);
42     if(s->len == 0) printf("No Path!");
43     else for(int i = 0; i < s->len + 1; i++)
44             printf("(%d %d)", s->path[i].x, s->path[i].y);
45     return 0;
46 }
47 
48 Stack* create_emptystack() {
49     Stack *S;
50     S = (Stack*)malloc(sizeof(Stack));
51     if(S == NULL)
52         printf("malloc error\n");
53     else
54         S->len = -1;
55     return S;
56 }
57 
58 int isempty(Stack *s) {
59     return s->len == -1;
60 }
61 
62 void push_stack(Stack *s, position pos) {
63     if(s->len > 10001)
64         printf("exceed!\n");
65     else {
66         s->len++;
67         s->path[s->len] = pos;
68     }
69 }
70 
71 void pop_stack(Stack *s) {
72     if(!isempty(s))
73         s->len--;
74 }
75 
76 //position get_top(Stack *s) {return s->path[s->len];}
77 
78 int judge(position p) {
79     return a[p.x][p.y] == 0 && p.x >= 0 && p.x < m && p.y >= 0 && p.y < n; //沒有走並且沒有超界
80 }
81 
82 int dfs(Stack *s, position now) {
83     int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; //上下左右四個方向
84     if(now.x == end.x && now.y == end.y) return 1; //如果當前節點是終點, 返回1
85     else{
86         a[now.x][now.y] = 1; //標記已走
87         for(int i = 0; i < 4; i++) {
88             position nextp;
89             nextp.x = dir[i][0] + now.x;
90             nextp.y = dir[i][1] + now.y;
91             if(!judge(nextp)) continue; //如果下一個節點不合法, 那么直接退出
92             push_stack(s, nextp); //先把下一個節點壓入
93             if(dfs(s, nextp)) return 1; //如果子節點中最終可以找到終點, 那么直接結束
94             pop_stack(s); //如果不能, 那么把下一個節點彈出, 並且進行下一個循環
95         }
96         a[now.x][now.y] = 0;
97         return 0; //如果找不到, 那么直接返回0
98     }
99 }
 
        

本題的要點是給dfs函數設置返回值來表示是否有到終點的通路。

3.最短路徑(bfs):

 

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <math.h>
  5 
  6 typedef struct {
  7     int x;
  8     int y;
  9     int pre; //記錄該結點的父結點(來源)
 10 }position;
 11 
 12 typedef struct my_queue {
 13     position *que;
 14     int front;
 15     int last;
 16 }Queue;
 17 
 18 Queue* create_emptyqueue();
 19 int isempty(Queue *q);
 20 void push_queue(Queue *q, position x);
 21 void pop_queue(Queue *q);
 22 
 23 int a[100][100];
 24 Queue *bfs(position st);
 25 void print(Queue *q, position ans);
 26 
 27 position begin, end;
 28 int m, n, flag = 0;
 29 
 30 
 31 int main() {
 32     int i, j;
 33     Queue *q;
 34     scanf("%d%d", &m, &n);
 35     scanf("%d%d%d%d", &begin.x, &begin.y, &end.x, &end.y);
 36     begin.pre = -1;
 37     for(i = 0; i < m; i++) {
 38         for(j = 0; j < n; j++)
 39             scanf("%d", &a[i][j]);
 40     }
 41     q = bfs(begin);
 42     if(!flag) printf("No Path!");
 43     else {
 44         print(q, q->que[q->front - 1]);
 45         printf("(%d %d)", end.x, end.y);
 46     }
 47     return 0;
 48 }
 49 
 50 Queue *create_emptyqueue() {
 51     Queue *p;
 52     p = (Queue*)malloc(sizeof(Queue));
 53     if(p != NULL) {
 54         p->que = (position*)malloc(10000*sizeof(position));
 55         if(p->que != NULL) {
 56             p->front = 0;
 57             p->last = 0;
 58             return p;
 59         }
 60         else free(p);
 61     }
 62     return NULL;
 63 }
 64 
 65 int isempty(Queue *q) {
 66     return q->front == q->last;
 67 }
 68 
 69 void push_queue(Queue *q, position x) {
 70     if(q->last + 1 == q->front)
 71         printf("full\n");
 72     else {
 73         q->que[q->last] = x;
 74         q->last = q->last + 1;
 75     }
 76 }
 77 
 78 void pop_queue(Queue *q) {
 79     if(q->front == q->last)
 80         printf("empty\n");
 81     else
 82         q->front = q->front + 1;
 83 }
 84 
 85 Queue *bfs(position st) {
 86     int pr, i;
 87     int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
 88     position former, latter;
 89     position t;
 90     Queue *q = create_emptyqueue();
 91     former = st;
 92     push_queue(q, former);
 93     a[former.x][former.y] = 1;
 94     while(!isempty(q)) { //隊列不為空,說明可能還有可走的路
 95         latter = q->que[q->front];
 96         pr = q->front;
 97         pop_queue(q);
 98         for(i = 0; i < 4; i++) {
 99             t.x = latter.x + dir[i][0];
100             t.y = latter.y + dir[i][1];
101             t.pre = pr; //記錄該結點的來源
102             if(t.x == end.x && t.y == end.y) {
103                 flag = 1;
104                 return q;
105             }
106             if(!a[t.x][t.y] && t.x >= 0 && t.x < m && t.y >= 0 && t.y < n) {
107                 push_queue(q, t);
108                 a[t.x][t.y] = 1;
109             }
110         }
111     }
112     return q;
113 }
114 
115 void print(Queue *q, position ans) { //遞歸輸出
116     if(ans.pre == -1) {
117         printf("(%d %d)", ans.x, ans.y);
118         return ;
119     }
120     else {
121         print(q, q->que[ans.pre]);
122         printf("(%d %d)", ans.x, ans.y);
123     }
124 }

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM