标签:path ++ space ges ack 非递归 技术分享 ret pat
假定迷宫如下:1代表墙,0代表道路,起点在(1,1),终点(11,9)(PS:下标从0开始计算)。
现在寻求一条路径能从起点到达终点(非最短)。
有两种解法:递归与非递归。
递归算法思路:
要用递归,就要寻找一个子问题,该子问题是递归的。很明显,这道题的子问题就是从8个方向(上下左右还有四个斜角)中寻找一个可行方向并向前走一步,该子问题(seekPath函数)的实现代码如下:
1 struct offset{ 2 int x; 3 int y; 4 }; 5 offset move[8]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};//8个不同行动方向下的x和y偏移量 6 int mark[12][12]={0};//将数组所有节点访问位置0(未访问) 7 char a[][13]={ "111111111111", 8 "101101101111", 9 "110010011111", 10 "110111111111", 11 "111001111111", 12 "111110001111", 13 "111010110111", 14 "110101111011", 15 "110111111111", 16 "110100001111", 17 "110011100111", 18 "111111111011" 19 };//迷宫数组 20 list<offset> s;//存放成功路径 21 22 int seekPath(int x,int y){//行动一步 23 int next_x,next_y; 24 if(x==11&&y==9) return 1;//找到出口 25 for(int i=0;i<8;i++){//朝8个方向试探下一步 26 next_x=move[i].x+x; 27 next_y=move[i].y+y; 28 if(mark[next_x][next_y]==0&&a[next_x][next_y]==‘0‘){//下一步未走过并且是道路 29 mark[next_x][next_y]=1;//标记该点已经走过 30 if(seekPath(next_x,next_y)){ 31 offset a={next_x,next_y}; 32 s.push_front(a); //记录正确路径 33 return 1; 34 } 35 } 36 } 37 if(x==1&&y==1){//死迷宫 38 cout<<"failed"<<endl; 39 } 40 return 0; 41 }
递归过程中,在每个点上有8个方向,在某个方向上若能满足“该方向点未走过并且是道路 ”的条件,即可执行下一步(下一步的方向从第一个方向重新开始计算),直到找到递归出口。递归出口自然是行走到终点的情况。
测试代码如下:
1 int main(){//测试代码 2 mark[1][1]=1; 3 if(seekPath(1,1)) 4 s.push_front(offset{1,1}); 5 list<offset>::iterator it=s.begin(); 6 while(it!=s.end()){ 7 cout<<"("<<it->x<<","<<it->y<<")"; 8 it++; 9 } 10 return 0; 11 }
非递归算法思路:
我们首先需要一个辅助链表,链表的作用是为了记录正确路径。从起点开始,有8个方向,若能满足“该方向点未走过并且是道路 ”的条件,即可将该点放入表尾并执行下一步(下一步的方向从第一个方向重新开始计算),当8个方向都不能满足条件时,将该点从表尾删除并回退到上一个点。实现代码如下:
1 #include <iostream> 2 #include <list> 3 using namespace std; 4 struct offset{ 5 int x; 6 int y; 7 }; 8 struct point{ 9 int x; 10 int y; 11 }; 12 offset move[8]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};//8个不同行动方向下的x和y偏移量 13 int mark[12][12]={0};//将数组所有节点访问位置0(未访问) 14 char a[][13]={ "111111111111", 15 "101101101111", 16 "110010011111", 17 "110111111111", 18 "111001111111", 19 "111110001111", 20 "111010110111", 21 "110101111011", 22 "110111111111", 23 "110100001111", 24 "110011100111", 25 "111111111011" 26 };//迷宫数组 27 28 int main(){//测试代码 29 mark[1][1]=1; 30 list<point> lists;//存放路径 31 point s={1,1}; 32 lists.push_back(s); 33 while(!lists.empty()){ 34 s=lists.back(); 35 for(int d=0;d<8;d++){//朝8个方向试探下一步 36 int x=s.x+move[d].x; 37 int y=s.y+move[d].y; 38 if(x==11&&y==9){//找到出口 39 s.x=x; 40 s.y=y; 41 lists.push_back(s); 42 goto end; 43 } 44 if(a[x][y]==‘0‘&&mark[x][y]==0){//下一步未走过并且是道路 45 mark[x][y]=1; 46 point temp={x,y}; 47 lists.push_back(temp); 48 s.x=x; 49 s.y=y; 50 d=0; 51 } 52 } 53 lists.pop_back();//删除不可达路径 54 } 55 cout<<"failed"; 56 end:list<point>::iterator it=lists.begin(); 57 while(it!=lists.end()){ 58 cout<<"("<<it->x<<","<<it->y<<")"; 59 it++; 60 } 61 return 0; 62 }
标签:path ++ space ges ack 非递归 技术分享 ret pat
原文地址:http://www.cnblogs.com/ytz1996/p/6298676.html