前面的《顺序栈和迷宫求解》中已经提到,用栈DFS的方法求得的路径是非最短路径。如果要求得最短路径需要进一步处理。
1. 增加一个全局数组(PrintType **g_MazeFootPrint),用来存放到某个节点的最短路径长度(shorteststep)和到达该节点的上一个节点位置(parent)。
typedef struct { PosType parent; int shorteststep; }PrintType; PrintType **g_MazeFootPrint;
2. 修改“是否可走”的条件,即修改如下函数:
1 Status MazePass(PosType pos, int x, int y) 2 { 3 if(pos.x>=0 && pos.y>=0 && pos.x<g_m && pos.y<g_n 4 && (g_MazeMap[pos.y][pos.x] == 0 || g_MazeFootPrint[y][x].shorteststep + 1 < g_MazeFootPrint[pos.y][pos.x].shorteststep)) 5 { 6 return OK; 7 } 8 return ERROR; 9 }
增加了一个判断条件,当到达目前节点的路径小于原有路径时,可重走此节点。同时修改到达当前节点的路径大小。
3. 当找到出口时不立即返回,而继续搜索;
代码如下:
define.h
// define.h #ifndef __MENGQL_DEFINE__ #define __MENGQL_DEFINE__ #define C_LOG_DBG(format, ...) //printf("[%s@%s,%d] " format ,__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); #define C_LOG_ERR(format, ...) printf("[%s@%s,%d] " format ,__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); typedef enum EStatus {ERROR, OK} Status; #endif
SqStack.h
// SqStack.h #ifndef __SQ_STACK_H__ #define __SQ_STACK_H__ #include "define.h" typedef struct { int x; int y; }PosType; typedef struct { PosType seat; int di; }SElemType; #define STACK_INIT_SIZE 100 typedef struct { SElemType* base; SElemType* top; int stacksize; }SqStack; extern Status InitStack(SqStack *S); extern Status GetTopStack(SqStack S, SElemType *e); extern Status PushStack(SqStack *S, SElemType e); extern Status PopStack(SqStack *S, SElemType *e); extern Status StackEmpty(SqStack *S); extern Status DestoryStack(SqStack *S); #endif
MazeShortPath.c
1 // MazeShortPath.c 2 #include <string.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include "define.h" 6 #include "SqStack.h" 7 8 9 typedef struct 10 { 11 PosType parent; 12 int shorteststep; 13 }PrintType; 14 15 PrintType **g_MazeFootPrint; 16 int **g_MazeMap; 17 int g_m, g_n;//g_m:列数 g_n:行数 18 19 #define FAILEDPOS 5 20 #define FOOTPRINT 2 21 22 void MazePrintRes(PosType *start, PosType *end) 23 { 24 PosType p; 25 if(end->x == start->x && end->y == start->y) 26 { 27 printf("[%d, %d]\n", start->x, start->y); 28 return; 29 } 30 else 31 { 32 p.x = g_MazeFootPrint[end->y][end->x].parent.x; 33 p.y = g_MazeFootPrint[end->y][end->x].parent.y; 34 MazePrintRes(start, &p); 35 printf("[%d, %d]\n", end->x, end->y); 36 return; 37 } 38 } 39 Status MazePass(PosType pos, int x, int y) 40 { 41 if(pos.x>=0 && pos.y>=0 && pos.x<g_m && pos.y<g_n 42 && (g_MazeMap[pos.y][pos.x] == 0 || g_MazeFootPrint[y][x].shorteststep + 1 < g_MazeFootPrint[pos.y][pos.x].shorteststep)) 43 { 44 return OK; 45 } 46 return ERROR; 47 } 48 void MazeFootPrint(PosType pos) 49 { 50 g_MazeMap[pos.y][pos.x] = FOOTPRINT; 51 } 52 void MarkPrint(PosType pos) 53 { 54 g_MazeMap[pos.y][pos.x] = FAILEDPOS; 55 } 56 void NextPos(PosType *pos, int di) 57 { 58 switch(di) 59 { 60 case 1: 61 pos->y = pos->y-1; 62 break; 63 case 2: 64 pos->x = pos->x-1; 65 break; 66 case 3: 67 68 pos->y = pos->y+1; 69 break; 70 case 4: 71 pos->x = pos->x+1; 72 break; 73 defult: 74 break; 75 } 76 } 77 Status MazeShortPath(PosType *start, PosType *end) 78 { 79 SqStack S; 80 int nCurStep = 0; 81 PosType curPos; 82 SElemType e; 83 int nPrevX = 0; 84 int nPrevY = 0; 85 Status ERes = ERROR; 86 87 curPos.x = start->x; 88 curPos.y = start->y; 89 if(InitStack(&S) != OK) 90 { 91 return ERROR; 92 } 93 do 94 { 95 if(MazePass(curPos, nPrevX, nPrevY) == OK) 96 { 97 g_MazeFootPrint[curPos.y][curPos.x].shorteststep = g_MazeFootPrint[nPrevY][nPrevX].shorteststep + 1; 98 g_MazeFootPrint[curPos.y][curPos.x].parent.x = nPrevX; 99 g_MazeFootPrint[curPos.y][curPos.x].parent.y = nPrevY; 100 101 e.di = 1; 102 e.seat.x = curPos.x; 103 e.seat.y = curPos.y; 104 105 MazeFootPrint(curPos); 106 PushStack(&S, e); 107 108 if(curPos.x == end->x && curPos.y == end->y) 109 { 110 ERes = OK; 111 } 112 nPrevX = e.seat.x; 113 nPrevY = e.seat.y; 114 NextPos(&curPos, e.di); 115 } 116 else 117 { 118 if(StackEmpty(&S) != OK) 119 { 120 PopStack(&S, &e); 121 while(e.di>=4 && StackEmpty(&S)!=OK) 122 { 123 MarkPrint(e.seat); 124 PopStack(&S, &e); 125 126 } 127 if(e.di < 4) 128 { 129 e.di++; 130 PushStack(&S, e); 131 nPrevX = e.seat.x; 132 nPrevY = e.seat.y; 133 NextPos(&e.seat, e.di); 134 135 curPos.x = e.seat.x; 136 curPos.y = e.seat.y; 137 } 138 } 139 } 140 }while(StackEmpty(&S) != OK); 141 DestoryStack(&S); 142 return ERes; 143 } 144 int main() 145 { 146 PosType start; 147 PosType end; 148 int i, j; 149 150 scanf("%d %d", &g_m, &g_n); 151 start.x = 0; 152 start.y = 0; 153 end.x = g_m-1; 154 end.y = g_n-1; 155 156 g_MazeMap = (int**)malloc(g_m*sizeof(int*)); 157 g_MazeFootPrint = (PrintType**)malloc(g_m*sizeof(PrintType*)); 158 for(i=0; i<g_m; ++i) 159 { 160 g_MazeMap[i] = (int*)malloc(g_n*sizeof(int)); 161 g_MazeFootPrint[i] = (PrintType*)malloc(g_n*sizeof(PrintType)); 162 } 163 164 for(i=0; i<g_m; ++i) 165 { 166 for(j=0; j<g_n; ++j) 167 { 168 scanf("%d", &g_MazeMap[i][j]); 169 } 170 } 171 if(MazeShortPath(&start, &end) == OK) 172 { 173 MazePrintRes(&start, &end); 174 } 175 else 176 { 177 printf("no way!\n"); 178 } 179 return 0; 180 }