用递归完成的,看上去比22楼代码简练,但实际上递归效率远低于循环效率,主要是深层递归时极有可能绕回来将一个本来层级值很小的设置成层级值很大,当然最终会设置正确,但已经降低效率了,代码如下,有些用于调试的代码可以去掉:
程序代码:
程序代码:#include<stdio.h>
#define N 11
void setlevel(int a[][N],int x,int y,int l)
{//设置指定坐标点层级,如果坐标点是出口则返回1,否则返回0
int i;
if(x<0||x>=N-1||y<0||y>=N-1||a[x][y]>N*N)return; //坐标不合格或碰到墙及出口退出递归
if(a[x][y]>l)a[x][y]=l; //要设置的层级小于已设置层级则设置,否则返回
else return;
for(i=1;i<9;i+=2)setlevel(a,x+i/3-1,y+i%3-1,l+1); //递归设置层级,这个步进算法很巧妙哦!
}
int findmin(int a[][N],int x,int y)
{//找坐标点周边层级最小的,找到后返回步进矢量
int i,j,k,x1,y1;
j=a[x][y];
for(i=1,k=0;i<9;i+=2)
{
x1=x+i/3-1;
y1=y+i%3-1;
if(x1>=0&&y1>=0&&x1<N&&y1<N&&a[x1][y1]!=N*N&&a[x1][y1]<j)
{
k=i;
j=a[x1][y1];
}
}
return k;
}
int shortpath(char a[][N])
{//找最短路径,找到则标注并返回1,否则返回0
int i,j,m;
int sx,sy,ex,ey,b[N][N];
sx=sy=ex=ey=-1;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
b[i][j]=N*N;
if(a[i][j]=='S')
{
sx=i;
sy=j; //记录入口坐标
}
if(a[i][j]=='E')
{
ex=i;
ey=j; //记录出口坐标
b[i][j]=N*N+1;
}
if(a[i][j]=='*')b[i][j]=N*N+2;
}
}
if(sx<0||sy<0||ex<0||ey<0)return 0; //没有出入口返回无路径
setlevel(b,sx,sy,1);
j=findmin(b,ex,ey);
if(!j)return 0; //路堵死了返回无路径
m=b[ex+j/3-1][ey+j%3-1];
while(ex!=sx||ey!=sy)
{
j=findmin(b,ex,ey);
if(!j)return 0; //路径意外错误返回无路径,这种情况肯定不会出现,可去掉
ex=ex+j/3-1;
ey=ey+j%3-1;
if(a[ex][ey]!='S')a[ex][ey]='o';
}
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)printf("%4d",b[i][j]);
printf("\n");
} //输出数据化的地图用于调试递归调用后的结果是否正确,正常后可去掉
return m;
}
int main()
{
char k[N][N]=
{
{" "},
{" S "},
{" "},
{" "},
{" "},
{" **** ****"},
{" "},
{" "},
{" "},
{" E "},
};
int i,m;
for(m=0;m<N;m++)printf("%s\n",&k[m][0]); //显示未标注路径的地图
if((i=shortpath(k)))
{
printf("Yes,最少 %d 步完成。\n",i);
for(m=0;m<N;m++)printf("%s\n",&k[m][0]); //显示标注路径的地图
}
else printf("No\n");
return 0;
}[此贴子已经被作者于2016-12-22 11:15编辑过]









我先收藏,有时间再慢慢消化~
