POJ-3984 迷宫问题结题报告(BFS+记录路径)


早上考完高数(这考试好水啊),回来补上昨晚的题解。

题目描述:

题目:https://vjudge.net/problem/POJ-3984
定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

输入:
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出:
左上角到右下角的最短路径,格式如样例所示。

样例:
Input:

0 1 0 0 0

0 1 0 1 0

0 0 0 0 0

0 1 1 1 0

0 0 0 1 0

Output:

(0, 0)

(1, 0)

(2, 0)

(2, 1)

(2, 2)

(2, 3)

(2, 4)

(3, 4)

(4, 4)

思路分析:

因为这道题涉及到最短路径,所以使用BFS是比较合适的。但这道题有个特点:需要记录路径,所以,需要在我们搜到最后的时候能够找得到他的上一步。
因此,想到的方法是:通过一个数组,记下这个过程中全部经过的点。当搜到最短路路径时,通过这个点内包含的上一个点的信息,一级一级地找到上一个点(这里我尝试使用了vector来存储这些点)。这样,每个点需要记录的信息就包括:该点的横坐标,纵坐标和该点上一步的信息。可以通过建立struct来保存信息。
这样,每搜到一个点,在将这个点压入队列的同时,也压入一个vector。搜索完成后再做处理。

typedef struct{
	int x;
	int y;
	int root;
} point;
int xx[]={1,0,-1,0};
int yy[]={0,-1,0,1};

int main()
{
	bool vis[6][6]={0};
	int floor[6][6]={0};
	for(int i=0;i<5;i++)
	{
		for(int j=0;j<5;j++)
		{
			cin>>floor[i][j];
		}
	}
	vector<point> temp;
	point t1={0,0,-1};
	queue<point> a;
	temp.push_back(t1);
a.push(t1);
k=0;
//搜索、输出。
return 0;
}

下面开始搜索:

while(true)
	{
		if(a.front().x==4&&a.front().y==4)//到达终点,终止搜索。
		{
			break;
		}
		else
		{
			for(int i=0;i<4;i++)
			{
				int dx=a.front().x+xx[i];
				int dy=a.front().y+yy[i];//点向四个方向移动生成下一个要搜的点
				if(floor[dx][dy]==0&&vis[dx][dy]==0&&dx>=0&&dy>=0&&dx<5&&dy<5)//确认不会越界、没有被访问过且可以被访问。
				{
					vis[dx][dy]=1;//标记已被访问过
					point t2={dx,dy,k};
					a.push(t2);//把该点压入队列
					temp.push_back(t2);//记录这一步。	
				}
			}
			a.pop();//搜索完这个点,弹出队列。
		}
		k++;//表示现在生成的这个点他的上一步是在数组中的哪个位置。
	}

走到这,这道题也差不多了。但是,还没完:
因为它不是从终点开始输出的,所以,我们还需要通过我们现在搜到的这个点root元素往回找出它的路径,在从起点开始(相当于逆序输出)。
这里,由于我联想到了LIFO,所以采用了一个栈来保存这些点:

stack<point> result;//建立栈
	result.push(a.front());//将终点压入
	point*p=&temp[a.front().root];//通过指针指向找到上一个点,其实可以不用,单纯顶一个整除也行。
	do
	{
		result.push(*p);//将这个过程中的点压入队列。
		p=&temp[p->root];//继续找上一个点。
	}while(p->root!=-1);//当root为-1时说明这个点是起点,在前面定义初点时留下的标记。
	result.push(*p);//压入初点
	while(!result.empty())//逆序输出
	{
		printf("(%d, %d)",result.top().x,result.top().y);
		if(result.size()!=1) cout<<endl;
		result.pop();
	}

完毕。

完整代码

#include <iostream>
#include <vector>
#include <queue>
#include <stack>
using namespace std; 
typedef struct{
	int x;
	int y;
	int root;
} point;
int xx[]={1,0,-1,0};
int yy[]={0,-1,0,1};

int main()
{
	bool vis[6][6]={0};
	int floor[6][6]={0};
	for(int i=0;i<5;i++)
	{
		for(int j=0;j<5;j++)
		{
			cin>>floor[i][j];
		}
	}
	vector<point> temp;
	point t1={0,0,-1};
	queue<point> a;
	temp.push_back(t1);
	a.push(t1);
	int k=0;
	while(true)
	{
		if(a.front().x==4&&a.front().y==4)
		{
			break;
		}
		else
		{
			for(int i=0;i<4;i++)
			{
				int dx=a.front().x+xx[i];
				int dy=a.front().y+yy[i];
				if(floor[dx][dy]==0&&vis[dx][dy]==0&&dx>=0&&dy>=0&&dx<5&&dy<5)
				{
					vis[dx][dy]=1;
					point t2={dx,dy,k};
					a.push(t2);
					temp.push_back(t2);			
				}
			}
			a.pop();
		}
		k++;
	}
	stack<point> result;
	result.push(a.front());
	//cout<<"("<<a.front().x<<","<<a.front().y<<")"<<endl;
	point*p=&temp[a.front().root];
	do
	{
		result.push(*p);
		p=&temp[p->root];
	}while(p->root!=-1);
	result.push(*p);
	while(!result.empty())
	{
		printf("(%d, %d)",result.top().x,result.top().y);
		if(result.size()!=1) cout<<endl;
		result.pop();
	}
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值