BFS record path (learning record)

Keywords: Algorithm Dynamic Programming

After learning BFS some time ago, I was very happy to find that oj had some problems to do! But the recording path baffled me again. Hurry to learn. This article is a review of BFS and its recording path methods.

Let's take an example: 1086 maze problem    1220 Look for homework   1654 Treasure House

Take 1654 as an example:

1654 Treasure House

I chose this question because I did it when I learned this method: P (not because I wanted to hang up my senior brother orz)

  The general meaning is that given a matrix of n*m, the matrix is composed of the characters $and # and the position of $can go, # can't go. Find the shortest distance from the upper left corner to the lower right corner and the maximum output path in dictionary order.

Obviously, the search method uses BFS, that is, the simulated queue search method, breadth first to find the shortest path, but we need to find the shortest path. The method we use is to separate the structure storage path.

The following description is based on code understanding:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <vector>
#include <map>
#include <queue>
#include <cstring>
#include <cmath>
#include <set>
#include <iterator>
using namespace std;
typedef long long ll;
#define maxn 10000005
#define INF 0x3f3f3f3f
const int mod=1e9+7;
//Multiple sets of input, remember to initialize before each cycle (array, stack, queue, some variables)!!!
const int N=13;
char c[N][N];
int n,m,x,y;
int ans,cnt;
int head,end;
bool vis[N][N];
int dx[4]={0,1,-1,0};
int dy[4]={-1,0,0,1};
char dir[N][N];
int val[N][N];

  When defining the variable part, pay attention to the direction arrays dx[4] and dy[4], and pay great attention to the initialization value, because we need to output the maximum according to the dictionary order, so the four directions according to the dictionary order should be w, s, N and E, and the two arrays should be assigned one by one according to the upper, north, lower, South, left, West, right and East (nonsense) (be careful, if you make a mistake, you must be WA).

struct node
{
	int x,y,time;
	node(){};
	node(int xx,int yy,int tt)
	{
		x=xx,y=yy,time=tt;
	}
};

struct direction//The array used for the recording direction, because the recording letters use character type, dir to record character variables 
{
	int x,y,time;
	char dir;
	direction(){};
	direction(int xx ,int yy,int tt,char dd)
	{
		x=xx,y=yy,time=tt,dir=dd;
	}
} e[100][100];

bool check(int xx,int yy)//Map problem must have operation: judge whether you can go 
{                        //That is, it is not beyond the boundary, but also a square that can be taken 
	if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&c[xx][yy]!='#') return true;
	else return false;
}

bool bfs()
{
	queue<node>q;
	node s(1,1,0);
	vis[1][1]=1;
	q.push(s);
	while(!q.empty())
	{
		node now=q.front();
		q.pop();
		if(now.x==n&&now.y==m)
		{
			ans=now.time;
			return true;
		}
		for(int i=0;i<4;i++)
		{
			int nx=now.x+dx[i];
			int ny=now.y+dy[i];
			if(check(nx,ny)&&!vis[nx][ny])
			{
				node nex(nx,ny,now.time+1);
				vis[nx][ny]=true;
				e[nx][ny].x=now.x;//It can be found that the coordinates of the previous step are stored here, because we need to find the final shortest path. There will be many paths in breadth first,
				e[nx][ny].y=now.y;//Once our conditions are met, the path that can go to the last step is the best path, so the previous step of this path must be a step on the final path 
				e[nx][ny].time=now.time+1;
				if(i==0)
				e[nx][ny].dir='W';
				else if(i==1)
				e[nx][ny].dir='S';
				else if(i==2)
				e[nx][ny].dir='N';
				else if(i==3)
				e[nx][ny].dir='E';//Then, the function of initializing and defining dx dy array in dictionary order can be reflected,
				q.push(nex);      //According to the ascending order of i, the final output must be the maximum dictionary order 
			}
		}
	}
	return false;
}

void print(int a, int b)
{
    if(a==1&&b==1) return;//Define the output function, as long as the answer path that can be pushed from the last coordinate to the first coordinate is output 
    print(e[a][b].x, e[a][b].y);//Recursive call function 
    printf("%c", e[a][b].dir);
}

The user-defined function part is explained in detail in the code (I'm not good at Chinese. If something is wrong, please forgive me ^ ^).

int main()
{
	//freopen("test.in","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
    	for(int j=1;j<=m;j++)
    	{
    		cin>>c[i][j];
		}
	}
	bfs();
	printf("%d\n", e[n][m].time);
    print(n, m);
    printf("\n");
	return 0;
}

In the main function part, bfs () and print () are called.

1220 Look for homework

When I do this problem, I feel very stupid, because you will find that there is no space between the input numbers, so the input is a string, and the int array cannot be defined... As a result, another student didn't trip over this point when he did it. It's because I'm too good, QAQ

This question is the smallest dictionary order, which is different from the one above

Put the AC code below:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <vector>
#include <map>
#include <queue>
#include <cstring>
#include <cmath>
#include <set>
#include <iterator>
using namespace std;
typedef long long ll;
#define maxn 10000005
#define INF 0x3f3f3f3f
const int mod=1e9+7;
//Multiple sets of input, remember to initialize before each cycle (array, stack, queue, some variables)!!!
const int N=13;
char a[N][N];
int n,m,x,y;
int ans,cnt;
int head,end;
bool vis[N][N],ac[N][N];
int dx[4]={1,0,0,-1};
int dy[4]={0,-1,1,0};

struct node
{
	int x,y,step;
	node(){};
	node(int xx,int yy,int ss)
	{
		x=xx,y=yy,step=ss;
	}
};

struct direction
{
	int x,y,step;
	char dir;
	direction(){};
	direction(int xx,int yy,int ss,char dd)
	{
		x=xx,y=yy,step=ss,dir=dd;
	}
} e[100][100];

bool check(int xx,int yy)
{
	if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]!='1') return true;
	else return false;
}

bool bfs()
{
	queue<node>q;
	node s(1,1,0);
	vis[1][1]=1;
	q.push(s);
	while(!q.empty())
	{
		node now=q.front();
		q.pop();
		if(now.x==n&&now.y==m)
		{
			ans=now.step;
			return true;
		}
		for(int i=0;i<4;i++)
		{
			int nx=now.x+dx[i];
			int ny=now.y+dy[i];
			if(check(nx,ny)&&!vis[nx][ny])
			{
				node nex(nx,ny,now.step+1);
				vis[nx][ny]=true;
				e[nx][ny].x=now.x;
				e[nx][ny].y=now.y;
				e[nx][ny].step=now.step+1;
				if(i==0)
				e[nx][ny].dir='D';
				else if(i==1)
				e[nx][ny].dir='L';
				else if(i==2)
				e[nx][ny].dir='R';
				else if(i==3)
				e[nx][ny].dir='U';
				q.push(nex);
			}
		}
	}
	return false;
}

void print(int a,int b)
{
	if(a==1&&b==1) return;
	print(e[a][b].x,e[a][b].y);
	printf("%c", e[a][b].dir);
}

int main()
{
	//freopen("test.in","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    	memset(a,0,sizeof(a));//Multi group input must remember to initialize before each input! 
    	memset(vis,0,sizeof(vis));
    	for(int i=1;i<=n;i++)
        {
        	for(int j=1;j<=m;j++)
    	    {
    		    cin>>a[i][j];
		    }
 	    }
	bfs();
	printf("%d\n", e[n][m].step);
        print(n, m);
        printf("\n");
	}
    
	
	return 0;
}

1086 maze problem

The difference in this question is that the output is coordinates. Pay attention to the format. There must be spaces where there are spaces. Generally, just copy the output sample directly and change the numbers. This problem is simpler. The problem tells you that there is a unique solution. You can directly output and record the shortest path. Note that the upper left corner of this place is given as (0,0). Don't write it as (1,1)!!!

AC Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <vector>
#include <map>
#include <queue>
#include <cstring>
#include <cmath>
#include <set>
#include <iterator>
using namespace std;
typedef long long ll;
#define maxn 10000005
#define INF 0x3f3f3f3f
const int mod=1e9+7;
//Multiple sets of input, remember to initialize before each cycle (array, stack, queue, some variables)!!!
int a[5][5];
int dx[4]={1,0,0,-1};
int dy[4]={0,1,-1,0};
int ans;
bool vis[5][5];

bool check(int xx,int yy)
{
	if(xx>=0&&xx<5&&yy>=0&&yy<5&&a[xx][yy]!=1) return true;
	else return false;
}

struct node
{
	int x,y,step;
	node(){};
	node(int xx,int yy,int ss)
	{
		x=xx,y=yy,step=ss;
	}
};

struct process
{
	int x,y;
} e[100][100];

bool bfs()
{
	queue<node>q;
	node s(0,0,0);
	vis[0][0]=true;
	q.push(s);
	while(!q.empty())
	{
		node now=q.front();
		q.pop();
		if(now.x==4&&now.y==4)
		{
			ans=now.step;
			return true;
		}
		for(int i=0;i<4;i++)
		{
			int nx=now.x+dx[i];
			int ny=now.y+dy[i];
			if(check(nx,ny)&&!vis[nx][ny])
			{
				node nex(nx,ny,now.step+1);
				e[nx][ny].x=now.x;
				e[nx][ny].y=now.y;
				vis[nx][ny]=true;
				q.push(nex);
			}
		}
	}
	return false;
}

void print(int a,int b)
{
	if(a==0&&b==0)
	{
		printf("(0, 0)\n");
		return;
	}
	print(e[a][b].x,e[a][b].y);
	printf("(%d, %d)\n",a,b);
}

int main()
{
	//freopen("test.in","r",stdin);
    for(int i=0;i<5;i++)
    {
    	for(int j=0;j<5;j++)
    	{
    		cin>>a[i][j];
		}
	}
	bfs();
	print(4,4);
	return 0;
}

The best way to beat forgetting is to review more and do more similar questions! Review more review more~

If there is any mistake, please give advice   Orz

Posted by shoombooltala on Mon, 22 Nov 2021 13:08:12 -0800