BFS训练总结

BFS确实可以,通过这几道题,算是最BFS有了一个更深的了解吧。其实原理都懂,也不是为了赚取流量,只是做个总结,就不写原理了。
A题算是一个简单的BFS探索吧。
在这里插入图片描述

#include <iostream>
#include<queue>

using namespace std;

const int maxn =1e5+5;

queue<int> q;

int vis[maxn],dis[maxn];

int n,k;
int ans=1;
void bfs(int n1)
{
    
    
	q.push(n1);
	vis[n1]=1;
	while(!q.empty())
	{
    
    
		int u,x=q.front();
		q.pop();
		for(int i=0;i<3;i++)
		{
    
    
			if(i==0)
				u=x+1;
			else if(i==1)
				u=x-1;
			else 
				u=x*2;
			if(u<0||u>maxn)
				continue;
			if(!vis[u])
			{
    
    
				vis[u]=1;
				q.push(u);
				dis[u]=dis[x]+1;
			}
			if(u==k)
				ans=dis[u];
		}
	}
}

int main()
{
    
    

	cin>>n>>k;
	if(n>=k)
	cout<<n-k<<endl;
	else
	{
    
    
		bfs(n);
		cout<<ans<<endl;
	}
}

B题

算是个板子题吧。只不过要用pair或者采用10*x+y存取路径,都要用到vector。

#include<iostream>
#include<vector>
#include<queue>


using namespace std;

int map[5][5];
#define  PII pair<int,int>
struct node {
    
    
	int x,y;
	vector<int> path;
};

queue<node> q;
int dx[]={
    
    0,1,0,-1},dy[]={
    
    -1,0,1,0};
void bfs(int s)
{
    
    
	node a;
	a.x=s/10,a.y=s%10;
	int x,y;
	x=a.x;
	y=a.y;
	a.path.push_back(10*x+y);
	q.push(a);
	while(!q.empty())
	{
    
    
		node temp;
		temp=q.front();
		q.pop();
		x=temp.x;
		y=temp.y;
		if(x==4&&y==4)
		{
    
    
			for(int i=0;i<temp.path.size();i++)
			{
    
    
				cout<<"("<<temp.path[i]/10<<", "<<temp.path[i]%10<<")"<<endl;
			}
		}
		for(int i=0;i<4;i++)
		{
    
    
			int a1=x+dx[i];
			int b1=y+dy[i];
			node temp1;
			temp1.path=temp.path;
			if(a1>=0&&a1<5&&b1>=0&&b1<5&&!map[a1][b1])
			{
    
    
				map[a1][b1]=1;
				temp1.x=a1;
				temp1.y=b1;
				temp1.path.push_back(a1*10+b1);
				q.push(temp1);
			}
		}
	}
}

int main()
{
    
    
	for(int i=0;i<5;i++)
		for(int j=0;j<5;j++)
			cin>>map[i][j];
	bfs(0);
}

C题

  • 注意
# 三维bfs的搜索数组
int dx[] = { 0,0,1,0,0,-1 };
int dy[] = { 0,1,0,0,-1,0 };
int dz[] = { 1,0,0,-1,0,0 };

就是个单纯板子题了。只不过数组开到三维。

#include <iostream>
#include<cstring>

#include<algorithm>
#include<queue>

using namespace std;

const int N = 35;
char map1[N][N][N];
bool pd[N][N][N];
int l, r, c;
int dis[N][N][N];

struct node
{
    
    
	int x, y, z;
};

int sx, sy, sz, ex, ey, ez;


int dx[] = {
    
     0,0,1,0,0,-1 };
int dy[] = {
    
     0,1,0,0,-1,0 };
int dz[] = {
    
     1,0,0,-1,0,0 };


void bfs(int x1, int y1, int z1)
{
    
    
	queue<node> q;
	q.push({
    
     x1,y1,z1 });
	while (!q.empty())
	{
    
    
		node temp = q.front();
		q.pop();
		int i, j, k;
		i = temp.x,j=temp.y,k=temp.z;
		pd[i][j][k] = 1;
		if (i == ex && j == ey && k == ez)
		{
    
    
			cout << "Escaped in " << dis[i][j][k] << " minute(s)." << endl;
			return;
		}
		for (int o = 0; o < 6; o++)
		{
    
    
			int m = i + dx[o], n = j + dy[o], p = k + dz[o];
			if (m<=0 || m>l || n<=0 || n>r || p<=0 || p>c || map1[m][n][p] == '#' ||pd[m][n][p] )
				continue;
			pd[m][n][p] = 1;
			dis[m][n][p] = dis[i][j][k] + 1;
			q.push({
    
     m,n,p });
		}
	}
	if (dis[ex][ey][ez] == 0)
		cout << "Trapped!" << endl;
}

void solve()
{
    
    
	//cin>>l>>r>>c;
	memset(pd, 0, sizeof(pd));
	memset(dis, 0, sizeof(dis));
	for (int i = 1; i <= l; i++)
	{
    
    
		for (int j = 1; j <= r; j++)
		{
    
    
			string s;
			cin >> s;
			for (int k = 1; k <= c; k++)
			{
    
    
				map1[i][j][k] = s[k - 1];
				if (map1[i][j][k] == 'S')
				{
    
    
					sx = i, sy = j, sz = k;
				}
				if (map1[i][j][k] == 'E')
				{
    
    
					ex = i, ey = j, ez = k;
				}
			}
		}
	}

	bfs(sx, sy, sz);

}

int main()
{
    
    
	while (cin >> l >> r >> c && l && r && c)
		solve();
	// int t;
	// cin >> t;
	// while (t--)
	// {
    
    

	// }
}

D题

在这里插入图片描述
这个题就强了,可以bfs,可以数论
粘一个大佬的bfs

  • 数论证明

在这里插入图片描述

E题

在这里插入图片描述
板子题,前几次wa在板子没写好,后几次wa在板子没写好。因为忘记考虑不是时间因素的走不出去,就是给多长时间都走不出去。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int a,b,c;
int vis[52][52][52],pos[52][52][52];
struct node
{
    
    
    int x,y,z;
    int t;
};
int dir[6][3]= {
    
    {
    
    1,0,0},{
    
    -1,0,0},{
    
    0,0,1},{
    
    0,0,-1},{
    
    0,1,0},{
    
    0,-1,0}};
int go(int x,int y,int z)
{
    
    
    if(0<=x&&x<a&&0<=y&&y<b&&0<=z&&z<c&&pos[x][y][z]==0)
        return 1;
    return 0;
}
int bfs(int m)
{
    
    
    node s,e;
    queue<node>Q;
    s.x=0;
    s.y=0;
    s.z=0;
    s.t=0;
    Q.push(s);
    while(!Q.empty())
    {
    
    
        s=Q.front();
        Q.pop();
        if(s.t>m)
            return -1;
        if(s.x==a-1&&s.y==b-1&&s.z==c-1&&s.t<=m)
            return s.t;
        int i;
        for(i=0; i<6; i++)
        {
    
    
            e.x=s.x+dir[i][0];
            e.y=s.y+dir[i][1];
            e.z=s.z+dir[i][2];
            if(go(e.x,e.y,e.z)&&!vis[e.x][e.y][e.z])
            {
    
    
                vis[e.x][e.y][e.z]=1;
                e.t=s.t+1;
                
                Q.push(e);
            }
        }
    }
    return -1;
}
int main()
{
    
    
    int  K,time,i,j,k,ans;
    scanf("%d",&K);
    while(K--)
    {
    
    
        scanf("%d%d%d%d",&a,&b,&c,&time);
        for(i=0; i<a; i++)
            for(j=0; j<b; j++)
                for(k=0; k<c; k++)
                    scanf("%d",&pos[i][j][k]);
        memset(vis,0,sizeof(vis));
        vis[0][0][0]=1;
        ans=bfs(time);
        printf("%d\n",ans);
    }
    return 0;
}

F 题

这题学问大了
在这里插入图片描述
先上代码

#include <bits/stdc++.h>

using namespace std;

const int N = 10;
int a[N][N];
int dx[]={
    
    0,-1,0,1};
int dy[]={
    
    1,0,-1,0};
int vis[N][N][7];
int n, m, sx, sy, ex, ey;

struct node
{
    
    
	int x, y, cnt, num;
};
int bfs()
{
    
    
	queue<node> q;
	q.push({
    
    sx, sy, 6, 0});
	a[sx][sy] = 0;
	while (q.size())
	{
    
    
		node u = q.front();
		q.pop();
		if (u.x == ex && u.y == ey)
			return u.num;
		for (int i = 0; i < 4; i++)
		{
    
    
			int tx = u.x + dx[i];
			int ty = u.y + dy[i];
			if (tx < 1 || tx > n || ty < 1 || ty > m || a[tx][ty] == 0)
				continue;
			if (a[u.x][u.y] != 4 && u.cnt - 1 > 0 && vis[tx][ty][u.cnt - 1] == 0)
			{
    
    
				q.push({
    
    tx, ty, u.cnt - 1, u.num + 1});
				vis[tx][ty][u.cnt - 1] = 1;
			}
			else if (a[u.x][u.y] == 4 && vis[tx][ty][5] == 0)
			{
    
    
				q.push({
    
    tx, ty, 5, u.num + 1});
				vis[tx][ty][5] = 1;
			}
		}
	}
	return -1;
}
int main()
{
    
    
	int t;
	cin>>t;
	while (t--)
	{
    
    
		memset(vis, 0, sizeof(vis));
		cin>>n>>m;
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				cin>>a[i][j];
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
			{
    
    
				if (a[i][j] == 2)
					sx = i, sy = j;
				if (a[i][j] == 3)
					ex = i, ey = j;
			}
		cout << bfs() << endl;
	}
	return 0;
}

这道题如果单纯是模板题最短路倒没什么,但是他加入了一个“4”,因为这个可以多出来6分钟。也就说走到这个格子,爆炸时间会增加6分钟。所以这个必须考虑。这也就说你可能选的是最短路,但是时间到了,但是这并不能判死刑,因为你可以可能通过绕所谓的远路来争取时间,也就是走4这个格子。但是bfs本身就是可以求最短路所以只要bfs,4不可以重复走,其他格子最多可以重复走5次,也就是如下的关键代码。

if (a[u.x][u.y] != 4 && u.cnt - 1 > 0 && vis[tx][ty][u.cnt - 1] == 0)
{
    
    
		q.push({
    
    tx, ty, u.cnt - 1, u.num + 1});
		vis[tx][ty][u.cnt - 1] = 1;
}
else if (a[u.x][u.y] == 4 && vis[tx][ty][5] == 0)
{
    
    
		q.push({
    
    tx, ty, 5, u.num + 1});
		vis[tx][ty][5] = 1;
}

G 题

呕吼这么短的题意,太棒了,那你就错了。
这个题要剪枝。

#include <bits/stdc++.h>
using namespace std;
int n, m, k;
struct node
{
    
    
	int x, y;
	int t = 0;
};
const int N = 1e3+5;
int vis[N][N];
char mp[N][N];
int dx[] = {
    
    -1, 0, 1, 0};
int dy[] = {
    
    0, 1, 0, -1};
int sx, sy, ex, ey;
int dist[N][N];
int bfs(int x, int y)
{
    
    
	node s, e;
	queue<node> Q;
	s.x = x;
	s.y = y;
	s.t = 0;
	Q.push(s);
	while (!Q.empty())
	{
    
    
		s = Q.front();
		Q.pop();
		if (s.x == ex && s.y == ey)
			return s.t;
		for (int i = 0; i < 4; i++)
		{
    
    
			for (int j = 1; j <= k; j++)
			{
    
    
				e.x = s.x + dx[i] * j;
				e.y = s.y + dy[i] * j;
				int x, y;
				x = e.x;
				y = e.y;
				e.t=s.t+1;
				if (x > 0 && x <= n && y > 0 && y <= m && mp[x][y] == '#'||(dist[x][y]!=0x3f3f3f3f&&dist[x][y]<s.t+1))
					break;
				if (x > 0 && x <= n && y > 0 && y <= m && mp[x][y] == '.' && !vis[x][y])
				{
    
    
					vis[x][y] = 1;
					dist[x][y]=e.t;
					Q.push(e);
				}
			}
		}
	}
	return -1;
}
int main()
{
    
    
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
		{
    
    
			cin >> mp[i][j];
			dist[i][j] = 0x3f3f3f3f;
		}
	cin >> sx >> sy >> ex >> ey;
	int ans = bfs(sx, sy);
	cout << ans << endl;
	return 0;
}

在这里插入图片描述
在这里插入图片描述
也就是如上两个图。然后不剪枝的话,第48个过不去测试样例。

  • 总结来说,bfs不难,但是不能单纯背板子,要灵活运用。一定要灵活。
  • 当然板子是基础。一定要找准剪枝点,然后主要bfs的条件。当然不用想为啥是最短路,这个很奇妙。

猜你喜欢

转载自blog.csdn.net/qq_46264636/article/details/112725144