a和b之间的最短路径需要在两个过程中确定。一个是距离标记过程,另一个是路径标记过程。在距离标记过程中,先从位置a开始,把从a可到达的相邻方格都标记为1(表示与a相距为1),然后把从编号为1的方格可到达的相邻方格都标记为2(表示也a相邻为2)。这个标记过程继续下去直到到达b或者没有可到达相邻方格为止。
距离标记过程结束之后,路径标记过程开始。从方格b开始首先移动到一个其编号比b的编号小1的相邻位置上。重复这个过程直至到达a为止。
为了实现距离标记过程,我们可以使用另外一个数组存储距离,亦可以重用数组grid。为了节约内存我们一般使用数组重用,但是这样障碍物会和距离为1的方格混合,所以我们选择将所有的距离标志都加2。
bool findpath()
{
if((start.row==finish.row)&&(start.col==finish.col))
{
pathLength=0;
return true;
}
position offset[4];
offset[0].row=0;offset[0].col=1;//右
offset[1].row=1;offset[1].col=0;//下
offset[2].row=0;offset[2].col=-1;//左
offset[3].row=-1;offset[3].col=0;//上
//初始化网络四周的weiqiang
for(int i=0;i<=size+1;i++)
{
grid[0][i]=grid[size+1][i]=1;//底部和顶部
grid[i][0]=grid[i][size+1]=1;//左边和右边
}
position here=start;
grid[start.row][start.col]=2;
int numOfNbrs=4;
//对可达的位置做标记
arrayQueue<position>q;
position nbr;
do{
//给相邻位置做标记
for(int i=0;i<numOfNbrs;i++)
{//检查相邻位置
nbr.row=here.row+offset[i].row;
nbr.col=here.col+offset[i].col;
if(grid[nbr.row][nbr.col]==0)
{
grid[nbr.row][nbr.col]=grid[here.row][here.col]+1;
if((nbr.col==finish.row)&&(nbr.col==finish.col))
break;
q.push(nbr);
}
}
if((nbr.row==finish.row)&&(nbr.col==finish.col))break;
if(q.empty())
return false;
here=q.front();
q.pop();
}while(true);
//构造路径
pathLength=grid[finish.row][finish.col]-2;
path=new position[pathLength];
//从终点回溯
here=finish;
for(int j=pathLength-1;j>=0;j--)
{
path[j]=here;
for(int i=0;i<numOfNbrs;i++)
{
nbr.row=here.row+offset[i].row;
nbr.col=here.col+offset[i].col;
if(grid[nbr.row][nbr.col]==j+2)break;
}
here=nbr;
}
return true;
}
代码解析:首先将开始点周围的0点(即可标记点)加一,然后将周围已标记点插入到队列,然后每次从队列头提取一个点并删除,然后将其周围的可标记点在其基础上加1。知道队列为空或者到达结束点。
然后在结束点开始回溯,每次寻找标记比前一个位置少一的节点。直到开始点。