[蓝桥杯2019初赛]迷宫-DFS、BFS两种方法

迷宫问题的最短路,加最小字典序
[蓝桥杯2019初赛]迷宫-DFS、BFS两种方法_第1张图片
迷宫文件maze.txt传送门
作者写的2019年B组蓝桥杯解集
.
.
.

DFS的版本

#include
#include
using namespace std;
const int ax[4]={0,0,1,-1};
const int ay[4]={1,-1,0,0};
const char dir[5]={'R','L','D','U'};
int maze[60][60],mins[60][60];
char a[2000];
int best;
string ans;
bool judge(int x,int y) {//判断这个点是否越界,是否走过。
	if(x>0&&x<=30&&y>0&&y<=50&&!maze[x][y])
		return true;
	return false;
}
void dfs(int x,int y,int pos) {
	if(pos>best)
		return ;
	if(x==30&&y==50) {
		string temp;
			for(int i=1;i<pos;i++)
				temp+=a[i];
		if(pos<best) {//是最短的路
			ans=temp;
			best=pos;
		}
		else if(pos==best&&temp<ans)	ans=temp;//在实现路时最短的同时,保证字典序最小。
		return ;
	}
	for(int i=0;i<4;i++) {
		int tempx=x+ax[i];
		int tempy=y+ay[i];
		if(judge(tempx,tempy)&&pos+1<=mins[tempx][tempy]) {
			maze[tempx][tempy]=1;
			mins[tempx][tempy]=pos+1;
			a[pos]=dir[i];
			dfs(tempx,tempy,pos+1);
			maze[tempx][tempy]=0;//回溯找短的路,或者时字典序最小的。
		}
	}
}
int main()
{
	freopen("D:\\MY\\ce.txt","r",stdin);
	memset(mins,1,sizeof(mins));
	best=1<<28;
	for(int i=1;i<=30;i++)
		for(int j=1;j<=50;j++) {
			char t;
			cin>>t;
			maze[i][j]=t-'0'; 
		}
	maze[1][1]=1;
	dfs(1,1,1);
	cout<<ans<<endl;
	return 0;
}

其中最重要的就是数组mins,这里记录了从起始位置到这里的最短步数,
l
l当这个点在可以到达终点的路径上时,也有可能有多种方式到这个点,所以一点更要保证时最小的步数到可以到达终点的路径上的点。

.
.
.
BFS版本

#include
#include
#include
const int ax[4]={1,0,0,-1};
const int ay[4]={0,-1,1,0};
const char dir[5]={'D','L','R','U'};
int maze[40][60];
using namespace std;
struct point {
	int x,y;
	string ans;
	point(int a,int b,string c):x(a),y(b),ans(c){}
};
bool judge(int x,int y) {
	if(x>0&&x<=30&&y>0&&y<=50&&!maze[x][y])
		return true;
	return false;
}
void bfs() {
	queue<point>ans;
	ans.push(point(1,1,""));
	maze[1][1]=1;
	while(!ans.empty()) {
		point temp=ans.front();
		ans.pop();
		if(temp.x==30&&temp.y==50) {
			cout<<temp.ans<<endl;
			return ;
		}
		for(int i=0;i<4;i++) {
			int tempx=temp.x+ax[i];
			int tempy=temp.y+ay[i];
			if(judge(tempx,tempy)) {
				maze[tempx][tempy]=1;
				ans.push(point(tempx,tempy,temp.ans+dir[i]));
			}
		}
	}
}
int main() {
	freopen("D:\\MY\\ce.txt","r",stdin);
	for(int i=1;i<=30;i++)
		for(int j=1;j<=50;j++) {
			char t;
			cin>>t;
			maze[i][j]=t-'0'; 
		}
	bfs();
	return 0;
}

这里就不用考虑回溯的问题,不用考虑是不是最短路的问题,但是可能有一个是不是字典序最小需要考虑,
.
于是我把这里的dir方向数组设置成了"D L R U"的顺序,保证了在步数最小的前提下最小字典序一定会最早出现。

DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
*
**
**
*


还有一点要注意的就是,我这里 用的是int数组存地图,地图之间没有空格,一定要先用char读取,或者直接用char数组表示地图。
.
就因为这个,我抑郁了好久,一直不知道哪里错了。

你可能感兴趣的:(蓝桥杯)