信息学奥赛一本通网站1255 迷宫问题 题解
今天做了一道广搜题目[我是传送门],还是老套的迷宫问题.
但是这个是需要记录路径,我之前也听说过这种题目,不过这是第一次做.
其实我一开始想了很长时间,想了很多实现不了的思路,不过我翻课本的时候
算了,不"虚伪"了,直接进入正题:
和普通的迷宫问题唯一的区别的需要记录路径,基本相当于"升级",我们可以定义一个数组pre[]来记录前驱或后继(本体显然是后继)
但本蒟蒻一开始想错了,写成了前驱,但是我很聪(lan)明(duo),写了一个stack,又倒过来一遍,大家凑活着看吧(大家看明白后可以自己写后继):
#include<bits/stdc++.h> using namespace std; int tot[5][5]; struct P {//定义结构体,因为是二维的,所以需要一个x一个y int x;//前驱横坐标 int y;//前驱纵坐标 }; P pre[5][5];int xx[5] = {0,-1,0,0,1},yy[5] = {0,0,-1,1,0 };//神奇的东西,一会就明白(之前用过的话当我没说) int a[5][5];//二维空间 queue<int>q;//广搜用的队列 stack <int> s;//偷懒用的栈 void print(int x2,int y2) {//打印 if(x2 == 0 && y2 == 0) {//如果存完了 while(s.empty() == 0) {//开始弹出 int a = s.top();//一定要定义一个a不然会反过来(写前驱的话) s.pop(); cout<<"("<<s.top()<<", "; s.pop(); cout<<a<<")"<<endl; } cout<<"("<<4<<", "<<4<<")"<<endl; exit(0); } int x3=pre[x2][y2].x,y3=pre[x2][y2].y;//没存完就递归存数(可以改循环) s.push(x3); s.push(y3); print(x3,y3);//递归 } void gs() {//广搜(看名字就能看出来我才不用什么BFs当名字,花里胡哨的) while(q.empty() == 0) { int x = q.front();//这里可以用两个队列一个存x一个存y,但我喜欢这样 q.pop(); int y = q.front(); q.pop(); for(int i=1; i<=4; i++) {//神奇的搜索,自己悟 int x2 = x + xx[i];//新节点的横坐标 int y2 = y + yy[i];//纵坐标 if(a[x2][y2] == 0 && x2 >= 0 && y2 >= 0 && x2 < 5 && y2 < 5) {//如果没搜过且不越界 q.push(x2);//存入 q.push(y2); tot[x2][y2] = tot[x][y] + 1;//每一个节点都是由他的上一个节点扩展,所以是上一个+1; a[x2][y2] = 1;//标记 if(pre[x2][y2].x == 0) {//如果是第一次搜 pre[x2][y2].x = x;//记录 pre[x2][y2].y = y; } } if(x2 == 4 && y2 == 4) {//到达终点 print(4,4);//打印 return ;//结束 } } } } int main() { for(int i=0; i<5; i++) {//输入 for(int j=0; j<5; j++) cin>>a[i][j]; } q.push(0);//以(0,0)为起点开始 q.push(0); gs();//搜索 return 0; }
这其实也是一个广搜问题模板(自己写的,可能不正规不如其他好),其他广搜也可以用这个当模板
ps:上面说的"神奇的东西"其实我也很难解释,大家想不明白可以画个图理解一下
作者: liuzitong
出处:http://www.cnblogs.com/lztzs/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。