題目來自於嚴蔚敏《數據結構》,參考偽代碼實現的程序:
1 #include <stdio.h> 2 #include <malloc.h> 3 //記錄通道塊在迷宮矩陣當中的橫、縱坐標 4 struct Position{ 5 int x; 6 int y; 7 }; 8 //放入棧當中的通道塊元素 9 struct SElement { 10 int ord;//記錄此通道塊在整個通道當中的次序 11 Position p;//記錄此通道塊在矩陣當中的位置 12 int di;//記錄下一次測試這一路徑的臨近路徑的位置 13 }; 14 //創建棧數據結構 15 #define STACK_INIT_SIZE 100 16 #define STACKINCREMENT 10 17 struct MyStack{ 18 SElement* base; 19 SElement* top; 20 int stacksize; 21 }; 22 //創建一個棧如果創建成功則返回1,否則就返回0 23 int InitStack(MyStack* s) 24 { 25 s->base=(SElement*)malloc(STACK_INIT_SIZE*sizeof(SElement));//為棧分配初始空間 26 if(!s->base) return 0; 27 s->top=s->base;//設定為空棧 28 s->stacksize=STACK_INIT_SIZE; 29 return 1; 30 } 31 //判斷棧是否為空,如果是空的就返回0,否則就返回1 32 int IsStackEmpty(MyStack* s) 33 { 34 if(s->top==s->base) return true; 35 return false; 36 } 37 //獲取棧頂元素,如果棧為空就返回0 否則就返回1 38 int GetTop(MyStack* s,SElement* e) 39 { 40 if(IsStackEmpty(s)) return 0; 41 e=s->top-1; 42 return 1; 43 } 44 //獲取棧的長度,並且通過程序返回 45 int StackLength(MyStack* s) 46 { 47 return s->top-s->base; 48 } 49 //插入元素e為新的棧頂元素,插入成功則返回1,否則返回0 50 int Push(MyStack* s,SElement e) 51 { 52 if(s->top-s->base>=STACK_INIT_SIZE) 53 { 54 s->base=(SElement*)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(SElement)); 55 if(!s->base) return 0; 56 s->top=s->base+s->stacksize; 57 s->stacksize+=STACKINCREMENT; 58 } 59 *(s->top)=e; 60 s->top++; 61 return 1; 62 } 63 //彈出棧頂元素賦值給e彈出成功返回1,彈出失敗返回0 64 int Pop(MyStack* s,SElement* e) 65 { 66 if(IsStackEmpty(s)) return 0; 67 *e=*(s->top-1); 68 s->top--; 69 return 1; 70 } 71 //定義牆元素為2 可走路徑為0 已知路徑為curStep 不能夠通過的路徑為-1 72 #define MazeScale 10 73 int Maze[MazeScale][MazeScale]={{2,2,2,2,2,2,2,2,2,2},{2,0,0,2,0,0,0,2,0,2},{2,0,0,2,0,0,0,2,0,2},{2,0,0,0,0,2,2,0,0,2}, 74 {2,0,2,2,2,0,0,0,0,2},{2,0,0,0,2,0,0,0,0,2},{2,0,2,0,0,0,2,0,0,2},{2,0,2,2,2,0,2,2,0,2},{2,2,0,0,0,0,0,0,0,2},{2,2,2,2,2,2,2,2,2,2}}; 75 //輔助函數考察當前路徑能否通過 76 bool Pass(Position posi) 77 { 78 //只有路徑所在位置的數字為0的是可以走的 79 if(Maze[posi.x][posi.y]==0) 80 { 81 return true; 82 } 83 return false; 84 } 85 //按順時針方向從東開始尋找矩陣當中某一個位置的臨近位置 86 Position NextPosition(Position now,int direction) 87 { 88 Position next; 89 int x=now.x; 90 int y=now.y; 91 switch(direction) 92 { 93 //東 94 case 1:{ 95 next.x=x; 96 next.y=y+1; 97 break; 98 } 99 //南 100 case 2:{ 101 next.x=x+1; 102 next.y=y; 103 break; 104 } 105 //西 106 case 3:{ 107 next.x=x; 108 next.y=y-1; 109 break; 110 } 111 //北 112 case 4: 113 { 114 next.x=x-1; 115 next.y=y; 116 break; 117 } 118 default:break; 119 } 120 return next; 121 } 122 //留下足跡 123 void FootPrint(Position p,int step) 124 { 125 Maze[p.x][p.y]=step; 126 } 127 //路徑不可走的話就留下-1的標記 128 void MarkPrint(Position p) 129 { 130 Maze[p.x][p.y]=-1; 131 } 132 int main() 133 { 134 //打印出迷宮矩陣 135 for(int i=0;i<MazeScale;i++) 136 { 137 for(int j=0;j<MazeScale;j++) 138 { 139 printf("%d ",Maze[i][j]); 140 } 141 printf("\n"); 142 } 143 //迷宮程序主體 144 MyStack path;//記錄路徑的棧 145 InitStack(&path);//初始化路徑數組 146 Position curp;//當前被試位置 147 //初始化當前位置為矩陣入口 148 curp.x=1; 149 curp.y=1; 150 int curStep=1;//被探索的步數 151 do 152 { 153 if(Pass(curp)) 154 { 155 FootPrint(curp,curStep);//可走就在迷宮里面留下足跡 156 //創建一個棧元素,存儲可行路徑的相關值,將這個元素存儲到棧當中 157 SElement e; 158 e.di=1;//意味着下一個被試路塊為這一個路塊的正上方的路塊 159 e.ord=curStep; 160 e.p.x=curp.x; 161 e.p.y=curp.y; 162 Push(&path,e);//將路徑塊入棧 163 if(curp.x==MazeScale-2 && curp.y==MazeScale-2) break; //如果被壓入的路徑塊到了迷宮的終點就退出循環 164 //找到下一個被試塊 165 curp=NextPosition(curp,1);//找到前一個被試塊東面的路徑塊作為被試塊 166 curStep++;//被探索的步數加一 167 }else//如果當前被試路徑不能夠通過的話 168 { 169 if(!IsStackEmpty(&path)) 170 { 171 SElement e; 172 Pop(&path,&e); 173 curStep--; 174 //將這一段所有的周圍路徑都已經被測試過的路徑從棧中清除 175 while(e.di==4 && !IsStackEmpty(&path)){ 176 MarkPrint(e.p); 177 Pop(&path,&e); 178 curStep--; 179 } 180 //如果當前棧頂還有未被測試的路徑就測試剩余的周圍路徑 181 if(e.di<4) 182 { 183 curp=NextPosition(e.p,e.di+1); 184 e.di++; 185 curStep++; 186 Push(&path,e); 187 } 188 } 189 } 190 }while(!IsStackEmpty(&path)); 191 printf("\n"); 192 //打印出結果迷宮矩陣 193 for(int i=0;i<MazeScale;i++) 194 { 195 for(int j=0;j<MazeScale;j++) 196 { 197 printf("%d ",Maze[i][j]); 198 } 199 printf("\n"); 200 } 201 return 0; 202 }