算法思想:广搜+优先队列
注意点:题目要求的是输出最短路径上的最少路段数,换句话说就是要求尽量少转弯。因此在每次搜索时,尽量沿着一个方向走到底!(这是本题的关键点)
代码:
#include<stdio.h>
#include<string.h>
#define max 80
int t[3][5] = {{0,0,-1,1},{-1,1,0,0}};//状态转移向量
char chess[max][max];//记录图节点
int vis[max][max];//记录当前图的访问状态,已访问置1,未访问置0.
int dis[max][max];//记录从初始位置(x1,y1) -> 当前位置(i,j)所经过的路段数.
int x1,y1;
int x2,y2;
int w,h;
void bfs(int x,int y);
int main()
{
int c1=0;
while(scanf("%d%d",&w,&h)!=EOF&&(w||h)){
int i,j,c2=0;
for(i=0;i<max;i++)
for(j=0;j<max;j++)
chess[i][j] = ' ';
for(i=1;i<=h;i++){
getchar();
for(j=1;j<=w;j++){
scanf("%c",&chess[i][j]);
}
}
printf("Board #%d:\n",++c1);
while(scanf("%d%d%d%d",&y1,&x1,&y2,&x2)!=EOF&&(x1||y1||x2||y2)){
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
chess[x2][y2] = ' ';//为了能让目标位置能被正确访问到,把其置' ',表示可以访问.
bfs(x1,y1);
if(dis[x2][y2]==0){
printf("Pair %d: impossible.\n",++c2);
}
else{
printf("Pair %d: %d segments.\n",++c2,dis[x2][y2]);
}
chess[x2][y2] = 'X';//目标位置被访问之后,在下一组搜索测试之前,要把其置回'X'.
}
printf("\n");
}
return 0;
}
void bfs(int x,int y)
{
int i;
int queue[5000];
int head=0,tail=1;
int tmp = x*(w+2) + y;
queue[head] = tmp;
vis[x][y] = 1;
while(head<tail){
tmp = queue[head++];
x = tmp / (w+2);
y = tmp % (w+2);
if(x==x2&&y==y2) return;
for(i=0;i<4;i++){
int nx = x + t[0][i];
int ny = y + t[1][i];
//当前遍历到的位置没有超出图的边界,并且是可访问的节点,并且没有被访问过,那么访问它,并加入队列。
while(nx>=0&&nx<=h+1&&ny>=0&&ny<=w+1&&vis[nx][ny]==0&&chess[nx][ny]!='X'){
tmp = nx*(w+2) + ny;
vis[nx][ny] = 1;
dis[nx][ny] = dis[x][y] + 1;
queue[tail++] = tmp;
nx = nx + t[0][i];
ny = ny + t[1][i];
}
}
}
}