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的条件。当然不用想为啥是最短路,这个很奇妙。