题目:
迷宫的每个点是通道或者墙壁,设计程序生成一个固定迷宫从起点到终点的最简路径(ps:我这是写博客的时候才发现,原来出题那货说的是简单路径,意即不走重复路,我特么看错了……)
思路:
从起点开始,对整个迷宫进行广度优先遍历,找到终点则可保证这的确是最简路径(因为是广度优先,比当前步数更少的步数能走到的位置都已遍历结束)。还是暴力计算的一种形式。有鉴于迷宫这样的东西近似于图,规律是不定的,大概也只能这样了。
方案:
首先确定迷宫矩阵内每个点需要包含的信息:
typedef struct MazePoint
{
int value;//0表示空地,1表示走过,-1表示墙
int step;//到达这个点的最短步数
int best_mark;//该点是否在最短路径上
int last_ahead;//达成该最短步数的上一点是哪个方向走过来的 0 3 6 9
}MazePoint;
其中best_mark和last_ahead用于标记最短路径。
其次在完成广度优先遍历功能的时候,需要建立队列,将当前点的所有邻接点排入队列中,一直遍历到队列为空。而且,为了区分当前步数(即,需要让计算机知道,当前遍历的点为从起点起第几步能够走到的点),需要建立两个队列,交替排入,交替遍历至空。队列中只需要保留横纵坐标信息即可,其他信息可依照横纵坐标去迷宫点阵内找对应点。队列点结构如下:
typedef struct Point
{
int x,y;//横纵坐标
}Point;
在遍历找到了终点之后。利用从终点开始的“last_ahead"信息,找到前一点,将该点的best_mark标记为1,由此向上一直找到起点为止,则将且仅将整条最短路径上的所有点的best_mark设置为1
代码:
只将主程序部分的代码贴下,其他的队列操作、迷宫输入等没啥价值……
1 void Go(MazePoint **matrix) 2 { 3 //思路:利用队列对迷宫进行广度优先搜索,搜索到77则找到了最短路径。 4 Queue *head1,*tail1,*head2,*tail2;//两个队列,用以区分是否遍历完当前层 5 head1=tail1=head2=tail2=NULL; 6 7 int step=1;//从第1步开始 8 Point current_point={0,0};//从第00点开始 9 Point next_point; 10 matrix[0][0].last_ahead=6;//记初始方向为向下 11 QueueIn(&head1,&tail1,current_point); 12 while(1)//反正会找到77这个点的 13 { 14 if(step%2==0)//偶数步数,用queue 2; 15 { 16 while(head2!=NULL)//遍历所有queue2里的点 17 { 18 current_point=QueueOut(&head2,&tail2); 19 matrix[current_point.x][current_point.y].step=step; 20 if(current_point.x+1==7&¤t_point.y==7)//哎呀往下够着啦 21 { 22 matrix[7][7].last_ahead=6;//最后一步向下 23 matrix[7][7].step=++step; 24 break; 25 } 26 if(current_point.x==7&¤t_point.y+1==7)//哎呀往右够着啦 27 { 28 matrix[7][7].last_ahead=3;//最后一步向右 29 matrix[7][7].step=++step; 30 break; 31 } 32 if(current_point.x-1>=0&&matrix[current_point.x-1][current_point.y].step==0&&matrix[current_point.x-1][current_point.y].value!=-1)//当前点可以向上走 33 { 34 next_point.x=current_point.x-1; 35 next_point.y=current_point.y; 36 QueueIn(&head1,&tail1,next_point);//将它上方的这个点排入下一层队列 37 matrix[next_point.x][next_point.y].last_ahead=0;//记方向为向上 38 } 39 if(current_point.x+1<=7&&matrix[current_point.x+1][current_point.y].step==0&&matrix[current_point.x+1][current_point.y].value!=-1)//当前点可以向下走 40 { 41 next_point.x=current_point.x+1; 42 next_point.y=current_point.y; 43 QueueIn(&head1,&tail1,next_point);//将它下方的这个点排入下一层队列 44 matrix[next_point.x][next_point.y].last_ahead=6;//记方向为向下 45 } 46 if(current_point.y-1>=0&&matrix[current_point.x][current_point.y-1].step==0&&matrix[current_point.x][current_point.y-1].value!=-1)//当前点可以向左走 47 { 48 next_point.x=current_point.x; 49 next_point.y=current_point.y-1; 50 QueueIn(&head1,&tail1,next_point);//将它左方的这个点排入下一层队列 51 matrix[next_point.x][next_point.y].last_ahead=9;//记方向为向左 52 } 53 if(current_point.y+1<=7&&matrix[current_point.x][current_point.y+1].step==0&&matrix[current_point.x][current_point.y+1].value!=-1)//当前点可以向右走 54 { 55 next_point.x=current_point.x; 56 next_point.y=current_point.y+1; 57 QueueIn(&head1,&tail1,next_point);//将它右方的这个点排入下一层队列 58 matrix[next_point.x][next_point.y].last_ahead=3;//记方向为向右 59 } 60 } 61 } 62 else//奇数层数,用queue1 63 { 64 while(head1!=NULL)//遍历所有queue1里的点 65 { 66 current_point=QueueOut(&head1,&tail1); 67 matrix[current_point.x][current_point.y].step=step; 68 if(current_point.x+1==7&¤t_point.y==7)//哎呀往下够着啦 69 { 70 matrix[7][7].last_ahead=6;//最后一步向下 71 matrix[7][7].step=++step; 72 break; 73 } 74 if(current_point.x==7&¤t_point.y+1==7)//哎呀往右够着啦 75 { 76 matrix[7][7].last_ahead=3;//最后一步向右 77 matrix[7][7].step=++step; 78 break; 79 } 80 if(current_point.x-1>=0&&matrix[current_point.x-1][current_point.y].step==0&&matrix[current_point.x-1][current_point.y].value!=-1)//当前点可以向上走 81 { 82 next_point.x=current_point.x-1; 83 next_point.y=current_point.y; 84 QueueIn(&head2,&tail2,next_point);//将它上方的这个点排入下一层队列 85 matrix[next_point.x][next_point.y].last_ahead=0;//记方向为向上 86 } 87 if(current_point.x+1<=7&&matrix[current_point.x+1][current_point.y].step==0&&matrix[current_point.x+1][current_point.y].value!=-1)//当前点可以向下走 88 { 89 next_point.x=current_point.x+1; 90 next_point.y=current_point.y; 91 QueueIn(&head2,&tail2,next_point);//将它下方的这个点排入下一层队列 92 matrix[next_point.x][next_point.y].last_ahead=6;//记方向为向下 93 } 94 if(current_point.y-1>=0&&matrix[current_point.x][current_point.y-1].step==0&&matrix[current_point.x][current_point.y-1].value!=-1)//当前点可以向左走 95 { 96 next_point.x=current_point.x; 97 next_point.y=current_point.y-1; 98 QueueIn(&head2,&tail2,next_point);//将它左方的这个点排入下一层队列 99 matrix[next_point.x][next_point.y].last_ahead=9;//记方向为向左 100 } 101 if(current_point.y+1<=7&&matrix[current_point.x][current_point.y+1].step==0&&matrix[current_point.x][current_point.y+1].value!=-1)//当前点可以向右走 102 { 103 next_point.x=current_point.x; 104 next_point.y=current_point.y+1; 105 QueueIn(&head2,&tail2,next_point);//将它右方的这个点排入下一层队列 106 matrix[next_point.x][next_point.y].last_ahead=3;//记方向为向右 107 } 108 } 109 } 110 if(matrix[7][7].step!=0)//走到了 111 break; 112 ++step; 113 // printf("For test:step=%d\n",step); 114 } 115 116 //如果正常运行到这里,那么搜索已经成功啦!下一步是按照崔爷的最后一步坑爹要求, 117 //把最佳路径画出来! 118 current_point.x=7; 119 current_point.y=7;//从终点起 120 while(current_point.x!=0||current_point.y!=0)//没走到起点就继续 121 { 122 matrix[current_point.x][current_point.y].best_mark=1;//该点在最佳路径上 123 if(matrix[current_point.x][current_point.y].last_ahead==0)//上一点向上来的 124 ++current_point.x; 125 else if(matrix[current_point.x][current_point.y].last_ahead==3)//上一点向右来的 126 --current_point.y; 127 else if(matrix[current_point.x][current_point.y].last_ahead==6)//上一点下来的 128 --current_point.x; 129 else//上一点向左来的 130 ++current_point.y; 131 } 132 matrix[0][0].best_mark=1;//起点当然也在最佳路径上 133 }
这就够长的了……中间的if条件长的令人蛋疼……