【vjudge训练记录】大一寒假专项训练——BFS
训练情况
A题
BFS模板题,BFS需要开一个队列记录当前搜索到的坐标,每次从队头取出来一个往其他方向遍历,记得判断移动后的位置是否合法,马显然可以往八个方向走,我们先初始化步数为 -1,然后起点位置步数为 \(0\),每次移动时步数等于原来的地方步数 +1,直接记录步数即可
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
#define pii pair<int,int>
using namespace std;
const int N = 403;
int n,m,x,y;
bool v[N][N];
int u[8][2] = {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
int ans[N][N];
bool pd(int x,int y){
return x>=1&&y>=1&&x<=n&&y<=m&&v[x][y]==0;
}
void bfs(int stx,int sty){
ans[stx][sty] = 0;
queue<pii> q;
q.push({stx,sty});
while(q.size()){
int x = q.front().first;
int y = q.front().second;
q.pop();
if(v[x][y]) continue;
v[x][y] = 1;
for(int i = 0;i<8;i++){
int xx = x + u[i][0];
int yy = y + u[i][1];
if(!pd(xx,yy)) continue;
ans[xx][yy] = ans[x][y] + 1;
q.push({xx,yy});
}
}
}
void solve(){
cin>>n>>m>>x>>y;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
ans[i][j] = -1;
}
}
bfs(x,y);
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
cout<<ans[i][j]<<" ";
}
cout<<endl;
}
}
signed main(){
// int T; cin>>T; while(T--)
solve();
return 0;
}
B题
这题还可以用并查集做,维护连通性再统计个数。BFS做法是遇到细胞就答案+1然后搜索,把相邻的细胞全部标记掉,如果遇到同一个细胞由于有标记就不会重复搜索
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
#define pii pair<int,int>
using namespace std;
const int N = 403;
int n,m,x,y;
string s[N];
bool v[N][N];
int u[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int ans;
bool pd(int x,int y){
return x>=0&&y>=0&&x<n&&y<m&&v[x][y]==0&&s[x][y]!='0';
}
void bfs(int stx,int sty){
queue<pii> q;
q.push({stx,sty});
while(q.size()){
int x = q.front().first;
int y = q.front().second;
q.pop();
if(v[x][y]) continue;
v[x][y] = 1;
for(int i = 0;i<4;i++){
int xx = x + u[i][0];
int yy = y + u[i][1];
if(!pd(xx,yy)) continue;
q.push({xx,yy});
}
}
}
void solve(){
cin>>n>>m;
for(int i = 0;i<n;i++) cin>>s[i];
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(s[i][j] != '0' && !v[i][j]){
ans++;
bfs(i,j);
}
}
}
cout<<ans<<endl;
}
signed main(){
// int T; cin>>T; while(T--)
solve();
return 0;
}
C题
洪水是从边缘过来的,所以我们对矩阵的四条边进行BFS搜索,把相邻的 0 全部标记掉,遇到围墙过不去,最后全部遍历一遍,判断 0 的位置没有标记过就是洪水到不了的地方
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
#define pii pair<int,int>
using namespace std;
const int N = 403;
int n,m,x,y;
string s[N];
bool v[N][N];
int u[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int ans;
bool pd(int x,int y){
return x>=0&&y>=0&&x<n&&y<m&&v[x][y]==0&&s[x][y]=='0';
}
void bfs(int stx,int sty){
queue<pii> q;
q.push({stx,sty});
while(q.size()){
int x = q.front().first;
int y = q.front().second;
q.pop();
if(v[x][y]) continue;
v[x][y] = 1;
for(int i = 0;i<4;i++){
int xx = x + u[i][0];
int yy = y + u[i][1];
if(!pd(xx,yy)) continue;
q.push({xx,yy});
}
}
}
void solve(){
cin>>n>>m;
for(int i = 0;i<n;i++) cin>>s[i];
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(i == 0 || i == n-1 || m == 0 || m == m-1){
bfs(i,j);
}
}
}
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(s[i][j] == '0' && !v[i][j]) ans++;
}
}
cout<<ans<<endl;
}
signed main(){
// int T; cin>>T; while(T--)
solve();
return 0;
}
D题
这题我们需要观察到一个性质,无论如何走,三棱锥翻过的位置朝下的数字都是固定的,所以我们可以先处理能到的地方(三棱锥朝下的数字和给定的数字一样),之后进行 BFS 搜索求最短路即可
这题由于初始三棱锥的情况固定,所以我们通过手玩发现,对于奇数行朝下的数字一定是 4 3 2 1 4 3 2 1 这样的循环,对于偶数行朝下的数字一定是 1 2 3 4 1 2 3 4 这样的循环,我们预处理能到的地方,显然左右两侧都可以随便翻,由于三角形有尖头朝上和尖头朝下两种情况,所以对于奇数列可以往下走,偶数列可以往上走,BFS的方向数组在移动的时候需要注意一下即可,初始化答案为最大值,一旦能走到终点就更新答案取小值
点击查看代码
#include <bits/stdc++.h>
// #define int long long
#define endl '\n'
#define pii pair<int,int>
using namespace std;
const int N = 300;
int n;
int a[N][N],b[N][N],step[N][N];
bool v[N][N];
bool vis[N][N];
int edx,edy;
int u[4][2] = {{0,-1},{0,1},{1,1},{-1,-1}};
int ans = INT_MAX;
bool pd(int x,int y){
return x>=1&&x<=n&&y>=1&&y<=(2*x-1);
}
void bfs(int stx,int sty){
queue<pii> q;
q.push({stx,sty});
while(q.size()){
int x = q.front().first;
int y = q.front().second;
q.pop();
if(x == edx && y == edy){
ans = min(ans,step[x][y]);
}
if(vis[x][y] || !v[x][y]) continue;
vis[x][y] = 1;
for(int i = 0;i<4;i++){
if(y%2==0 && i==2) continue;
if(y%2==1 && i==3) continue;
int xx = x + u[i][0];
int yy = y + u[i][1];
if(!pd(xx,yy) || !v[xx][yy]) continue;
step[xx][yy] = step[x][y] + 1;
q.push({xx,yy});
}
}
}
void solve(){
cin>>n;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=2*i-1;j++){
cin>>a[i][j];
}
}
cin>>edx>>edy;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=2*i-1;j++){
if(i&1){
int x = j-1; x%=4;
b[i][j] = 4-x;
} else {
int x = j-1; x%=4;
b[i][j] = x+1;
}
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=2*i-1;j++){
if(a[i][j] == b[i][j]) v[i][j] = 1;
}
}
// for(int i = 1;i<=n;i++){
// for(int j = 1;j<=2*i-1;j++){
// cout<<v[i][j]<<" ";
// }
// cout<<endl;
// }
bfs(1,1);
if(ans == INT_MAX) cout<<-1<<endl;
else cout<<ans<<endl;
}
signed main(){
// int T; cin>>T; while(T--)
solve();
return 0;
}

浙公网安备 33010602011771号