POJ - 3984 迷宫问题链接
(一)题目的大概思路
本题本身是一个相当朴素的广搜题,因为考虑到要求最短路径,我们下意识的考虑用bfs,然而,本题难就难在要输出搜索的路径,显然,我们不能够直接从起点往终点开始搜,将每次可以走的地点立即输出。这样显然是不对的。对此,我们采取的措施是反着搜索,即从终点玩起点搜索并且,我们将记录每一个可以走的点,到终点的距离。
该方法的核心思想是:我们首先用广搜从终点,开始往起点搜索。记录每一个可以走的点到终点的距离,一直搜索到起点(我们会将这些所以的距离都存下在time数组里面)。然后,我们只需要从time[起点橫坐标][起点纵坐标] 开始遍历time数组,直到找到终点。
我们将其time的起点记为临时标记点,只要我们找到time 数组中某个距离值,正好是临时标记的值减1,那么这个值绝对是我们最短路径上的值,我们先输出这个值,再将这个值的点,再一次记为临时标记点,以此循环,直到我们找到time[终点橫坐标][终点纵坐标]。 (当然,我们最好将time[终点橫坐标][终点纵坐标]的值赋为1,这样更好处理)
说明:当然,我们能保证起点坐标必在最短路径上,那我们将起点作为第一个临时标记点,毫无问题,同时,只要能够保证我们所找到的那个点的距离值,正好是临时标记点的值 - 1(因为我们是从终点开始搜的)。那么也将会始终保证该点也在最短路径上。
(二)代码
#include <queue>
#include <string.h>
#include <math.h>
#include <iostream>
#include <stdio.h>
#define ll long long
using namespace std;
int mymap[10][10]; //储存图
int time[10][10]; //储存每一个可以走的点到终点距离。
bool check (int x,int y)
{
if(x<0||x>4) return false; //判断是否越界
if(y<0||y>4) return false; //判断是否越界
if(time[x][y]!=0) return false;//判断是否走过
if(mymap[x][y]==1) return false;//判断是否能走
return true;
}
int d[4][2]={ {-1,0},{1,0},{0,1},{0,-1}};
struct Node
{
int x,y;
};
void bfs()
{
queue <Node>q;
q.push( {4,4});
time[4][4]=1; //将终点到终点距离设为1,是为了方便处理。
while(!q.empty())
{
Node t= q.front();
q.pop();
if(t.x==0&&t.y==0) return; //找到起点弹出
for(int i=0;i<4;i++)
{
Node temp ={ t.x +d[i][0],t.y+d[i][1] };
if(check(temp.x,temp.y))
{
q.push(temp);
time[temp.x][temp.y]=time[t.x][t.y]+1;
}
}
}
}
int main(){
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
scanf("%d",&mymap[i][j]);
}
}
bfs();
printf("(0, 0)\n"); //直接输出起点坐标即可
int x=0,y=0;
while(x!=4||y!=4)
{
for(int i=0;i<4;i++)
{
int tx=x+d[i][0];
int ty=y+d[i][1];
if(tx>=0&&ty>=0&&tx<=4&&ty<=4)
{
if(time[tx][ty]==time[x][y]-1)
//这样的time[tx][ty]必在最短路径上。
{
x=tx; // 将最短路径上的点替换为临时标记点
y=ty;
printf("(%d, %d)\n",tx,ty);
break;
}
}
}
}
return 0;
}