POJ 2984 迷宫问题(搜索 路径的还原)


迷宫问题
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u



Description

定义一个二维数组: 
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表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample 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

Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)


这道题我是用 bfs 写,Mzx 说可以用dfs写,并且记录路径的方式还简单,我想了一下,用dfs 确实简单了很多,今天我就先贴出bfs代码,有时间再写个 dfs 代码粘出来,我这个写的复杂了,本来简单的问题被我写的复杂了好多,唉,本事不到家啊!差的太远


附上代码1:(bfs)

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int d[4][2] = {1,0,-1,0,0,1,0,-1},visit[10][10];

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,};
struct A
{
	int x,y,step;
	int a[50],b[50];
};

void bfs(int x1,int y1,int x2,int y2)
{
	int s,t;
	queue<A> Q;
	A e;
	e.x = x1;
	e.y = y1;
	e.step = 0;
	e.a[e.step] = e.x;
	e.b[e.step] = e.y;
	Q.push(e);
	visit[x1][y1] = 1;
	while(!Q.empty())
	{
		e = Q.front();
		if(e.x == x2 && e.y == y2)
		{
			for(int i = 0;i <= e.step;i++)
			{
				printf("(%d, %d)\n",e.a[i],e.b[i]);
			}
			return;
		}
		Q.pop();
		for(int i = 0;i < 4;i++)
		{
			s = e.x + d[i][0];
			t = e.y + d[i][1];
			if(s >= 0 && s < 5 && t >= 0 && t < 5 && visit[s][t] == 0 && maze[s][t] == 0)
			{
				A e1;
				e1.x = s;
				e1.y = t;
				for(int j = 0;j <= e.step;j++)
				{
					e1.a[j] = e.a[j];
					e1.b[j] = e.b[j];
				}
				e1.step = e.step + 1;
				e1.a[e1.step] = s;
				e1.b[e1.step] = t;
				Q.push(e1);
				visit[s][t] = 1;
			}
		}
	}
}
int main()
{
	memset(visit,0,sizeof(visit));
	bfs(0,0,4,4);
	return 0;
}



附上代码2:(bfs)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
using namespace std;

int Map[10][10];
int dt[4][2] = {0,1,1,0,0,-1,-1,0};
struct point
{
	int x,y;
	int stop;
};

struct path
{
	int prev_x,prev_y;   // 该坐标的上一个坐标,也就是记录他是从哪一个坐标走过来的
	int New_x,New_y;    //  当前点的坐标
};

void bfs(int cur,int let,int st)
{
	path P_pa;         //  定义结构体,这点我这个代码里用的很糟,这点用了 大写 P 下面还有一个定义成 小写 p 大家注意点吧
	queue<point> Q;
	stack<path> p_path;
	P_pa.prev_x = -1;
	P_pa.prev_y = -1;
	P_pa.New_x = cur;
	P_pa.New_y = let;
	point q;
	Map[cur][let] = 1;
	q.x = cur;
	q.y = let;
	q.stop = st;
	Q.push(q);
	while(!Q.empty())
	{
		q = Q.front();
		Q.pop();
		if(q.x == 4 && q.y == 4)
		break;
		for(int i = 0;i < 4;i++)
		{
			int tx = q.x + dt[i][0];
			int ty = q.y + dt[i][1];
			if(tx >= 0 && tx < 5 && ty >= 0 && ty < 5 && !Map[tx][ty])
			{
				point qq;
				qq.stop = q.stop + 1;
				qq.x = tx;
				qq.y = ty;
				Q.push(qq);
				Map[tx][ty] = 1;
				P_pa.prev_x = q.x;
				P_pa.prev_y = q.y;
				P_pa.New_x = tx;
				P_pa.New_y = ty;
				p_path.push(P_pa);
			}
		}
	}

		while(!Q.empty())
		Q.pop();
		P_pa.prev_x = -1;
		P_pa.prev_y = -1;
		path p_pa;             // 定义的小写 p
		stack<point> ans;
		while(!p_path.empty())     //  从路径的记录中找到真正的那条路径
		{
			p_pa = p_path.top();
			p_path.pop();
			if(p_pa.New_x == 4 && p_pa.New_y == 4)
			{
				P_pa = p_pa;
			}
			 if(p_pa.New_x == P_pa.prev_x && p_pa.New_y == P_pa.prev_y)   //  找到该坐标的上一个坐标,就进行赋值,修改当前坐标,继续寻找上一个坐标
			 {
			 	point an;
			 	an.x = p_pa.New_x;
			 	an.y = p_pa.New_y;
			 	P_pa = p_pa;
			 	ans.push(an);       // 找到一个路径中的坐标,压入 ans 栈中
			 }
		}
		printf("(0, 0)\n");   //  在上面路径的寻找过程中 起始点和终止点是没有,储存的  所以直接输出,终止点下面输出
		while(!ans.empty())        //  依次访问 ans 栈,输出中间的路径
		{
			point an;
			an = ans.top();
			ans.pop();
			printf("(%d, %d)\n",an.x,an.y);
		}
		printf("(4, 4)\n");          //  输出终止点
}

int main()
{
	memset(Map,0,sizeof(Map));
	 for(int i = 0;i < 5;i++)
	 {
	 	for(int j = 0;j < 5;j++)
	 	{
	 		cin >> Map[i][j];
		}
	 }
	 bfs(0,0,0);
	 return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值