BFS刷题

BFS

离开山中路

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

typedef pair<int,int> PII;
const int N = 1010;
int n,x1,y1,x2,y2;
char g[N][N];
int dist[N][N]; //距离数组,开始要初始化为-1
int dx[] = {-1,1,0,0};
int dy[] = {0,0,-1,1};

int bfs()
{
    memset(dist,-1,sizeof(dist));
    dist[x1][y1] = 0;
    queue<PII> q;
    q.push({x1,y1});
    
    while(!q.empty())
    {
        auto [x,y] = q.front(); //取队首元素
        q.pop();
        
        for(int i = 0;i < 4;++i)
        {
            int a = x + dx[i],b = y + dy[i];
            
            if(a < 1 || a > n || b < 1 || b > n) continue;
            if(dist[a][b] != -1 || g[a][b] == '1') continue;
            
            dist[a][b] = dist[x][y] + 1;
            if(a == x2 && b == y2) return dist[a][b];
            q.push({a,b});
        }
    }
    return -1;
}

int main()
{
    cin >> n;
    for(int i = 1;i <= n;++i) cin >> (g[i]+1);
    cin >> x1 >> y1 >> x2 >> y2;
    //加入特判防止意外
    if(x1 == x2 && y1 == y2) cout << 0,exit(0);
    cout << bfs();
    return 0;
}

马的遍历

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

struct Node { int x, y; };
const int N = 405;
int ans[N][N], n, m, sx, sy;
int dx[] = {-2,-2,-1,1,2,2,1,-1};
int dy[] = {-1,1,2,2,1,-1,-2,-2};

void bfs() {
    queue<Node> q;
    memset(ans, -1, sizeof ans);
    ans[sx][sy] = 0;
    q.push({sx, sy});

    while (!q.empty()) {
        auto [x, y] = q.front();
        q.pop();
        
        for (int i = 0; i < 8; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx < 1 || nx > n || ny < 1 || ny > m) continue;
            if (ans[nx][ny] != -1) continue;
            
            ans[nx][ny] = ans[x][y] + 1;
            q.push({nx, ny});
        }
    }
}

int main() {
    cin >> n >> m >> sx >> sy;
    bfs();
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= m;++j)
        {
            cout << ans[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

好奇怪的游戏

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

struct Node { int x, y; };
int dx[] = {-2, -1, 1, 2, -2, 2, -2, 2, -2, -1, 1, 2};
int dy[] = {2, 2, 2, 2, 1, 1, -1, -1, -2, -2, -2, -2};
int dist[21][21]; // 坐标范围1~20

void bfs() {
    queue<Node> q;
    memset(dist, -1, sizeof dist);
    q.push({1, 1});
    dist[1][1] = 0;

    while (!q.empty()) {
        auto [x, y] = q.front();
        q.pop();

        for (int i = 0; i < 12; ++i) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx < 1 || nx > 20 || ny < 1 || ny > 20) continue;
            if (dist[nx][ny] != -1) continue;

            dist[nx][ny] = dist[x][y] + 1;
            q.push({nx, ny});
        }
    }
}

int main() {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;

    bfs();
    cout << dist[x1][y1] << endl << dist[x2][y2];
    return 0;
}

Bronze Lilypad Pond B

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct Node {
    int x, y, step;
};

int main() {
    int M, N, M1, M2;
    cin >> M >> N >> M1 >> M2;
    
    vector<vector<int>> pond(M, vector<int>(N));
    int start_x, start_y;
    
    // 读取池塘布局并定位起点
    for (int i = 0; i < M; ++i) {
        for (int j = 0; j < N; ++j) {
            cin >> pond[i][j];
            if (pond[i][j] == 3) {
                start_x = i;
                start_y = j;
            }
        }
    }
    
    // 生成8个跳跃方向
    const int dirs[8][2] = {
        {M1, M2}, {M1, -M2}, {-M1, M2}, {-M1, -M2},
        {M2, M1}, {M2, -M1}, {-M2, M1}, {-M2, -M1}
    };
    
    queue<Node> q;
    vector<vector<bool>> visited(M, vector<bool>(N, false));
    
    // 初始化队列
    q.push({start_x, start_y, 0});
    visited[start_x][start_y] = true;
    
    while (!q.empty()) {
        Node curr = q.front();
        q.pop();
        
        // 探索所有可能方向
        for (const auto& dir : dirs) {
            int nx = curr.x + dir[0];
            int ny = curr.y + dir[1];
            
            // 边界检查
            if (nx >= 0 && nx < M && ny >= 0 && ny < N) {
                // 直达终点
                if (pond[nx][ny] == 4) {
                    cout << curr.step + 1 << endl;
                    return 0;
                }
                // 有效莲花且未访问
                if (pond[nx][ny] == 1 && !visited[nx][ny]) {
                    visited[nx][ny] = true;
                    q.push({nx, ny, curr.step + 1});
                }
            }
        }
    }
    
    return 0; // 题目保证可达,此处不会执行
}

血色先锋队

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

typedef pair<int,int> PII;
const int N = 510;
int n,m,a,b;
int dist[N][N];
int dx[] = {-1,1,0,0},dy[] = {0,0,-1,1};

void bfs(queue<PII>& q)
{
    while(!q.empty())
    {
        auto [x,y] = q.front();q.pop();
        for(int i = 0;i < 4;++i)
        {
            int nx = x + dx[i],ny = y + dy[i];
            if(nx < 1 || nx > n || ny < 1 || ny > m) continue;
            if(dist[nx][ny] != -1) continue;
            dist[nx][ny] = dist[x][y] + 1;
            q.push({nx,ny});
        }
    }
}

int main()
{
    cin >> n >> m >> a >> b;
    queue<PII> q;
    memset(dist,-1,sizeof(dist));
    while(a--)
    {
        int x,y;cin >> x >> y;
        dist[x][y] = 0;
        q.push({x,y});
    }
    bfs(q);
    while(b--)
    {
        int x,y;cin >> x >> y;
        cout << dist[x][y] << endl;
    }
    return 0;
}

矩阵距离

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

const int N = 1005;
char g[N][N];
int dist[N][N];
int n,m;
int dx[] = {-1,1,0,0},dy[] = {0,0,-1,1};

void bfs()
{
    queue<pair<int,int>> q;
    memset(dist,-1,sizeof dist);
    for(int i = 0;i < n;++i)
    {
        for(int j = 0;j < m;++j)
        {
            if(g[i][j] == '1') 
            {
                dist[i][j] = 0;
                q.push({i,j});
            }
        }
    }
    while(!q.empty())
    {
        auto [x,y] = q.front(); q.pop();
        for(int i = 0;i < 4;++i)
        {
            int nx = x + dx[i],ny = y + dy[i];
            if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
            if(dist[nx][ny] == -1 && g[nx][ny] == '0')
            {
                dist[nx][ny] = dist[x][y] + 1;
                q.push({nx,ny});
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    for(int i = 0;i < n;++i) cin >> g[i];
    bfs();
    for(int i = 0;i < n;++i)
    {
        for(int j = 0;j < m;++j)
        {
            cout << dist[i][j];
            if(j != m-1) cout << " ";
        }
        cout << endl;
    }
    return 0;
}

填涂颜色

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

const int N = 35;
int n;
int g[N][N];
bool vis[N][N];
int dx[] = {-1,1,0,0},dy[] = {0,0,-1,1};

void bfs(int x,int y)
{
    queue<pair<int,int>> q;
    q.push({x,y});
    vis[x][y] = true;
    while(!q.empty())
    {
        auto [cx,cy] = q.front(); q.pop();
        for(int i = 0;i < 4;++i)
        {
            int nx = cx + dx[i],ny = cy + dy[i];
            if(nx < 0 || nx > n+1 || ny < 0 || ny > n+1) continue;
            if(g[nx][ny] == 1 || vis[nx][ny] == true) continue;
            vis[nx][ny] = true;
            q.push({nx,ny});
        }
    }
}

int main()
{
    cin >> n;
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= n;++j)
        {
            cin >> g[i][j];
        }
    }
    bfs(0,0);
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= n;++j)
        {
            if(g[i][j] == 1) cout << 1 << " ";
            else cout << (vis[i][j] == true ? 0 : 2) << " ";
        }
        cout << endl;
    }
    return 0;
}

拯救oibh总部

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

const int N = 505;
int n,m;
char g[N][N];
int dx[] = {-1,1,0,0},dy[] = {0,0,-1,1};

void bfs()
{
    queue<pair<int,int>> q;
    q.push({0,0});
    g[0][0] = '*';
    while(!q.empty())
    {
        auto [cx,cy] = q.front(); q.pop();
        for(int i = 0;i < 4;++i)
        {
            int nx = cx + dx[i],ny = cy + dy[i];
            if(nx < 0 || nx > n+1 || ny < 0 || ny > m+1) continue;
            if(g[nx][ny] == '*') continue;
            g[nx][ny] = '*';
            q.push({nx,ny});
        }
    }
}

int main()
{
    cin >> n >> m;
    memset(g,0,sizeof g);
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= m;++j)
        {
            cin >> g[i][j];
        }
    }
    bfs();
    int cnt = 0;
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= m;++j)
        {
            if(g[i][j] == '0') cnt++;
        }
    }
    cout << cnt;
    return 0;
}

Meteor Shower S流星雨

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

const int INF = 0x3f3f3f3f;
int star[350][350];  // 摧毁时间记录
bool vis[350][350];   // 访问标记
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};

struct Node {
    int x, y, time;
};

int main() {
    int m;
    cin >> m;
    memset(star, 0x3f, sizeof(star));
    memset(vis, 0, sizeof(vis));

    // 预处理流星摧毁时间
    for (int i = 0; i < m; ++i) {
        int x, y, t;
        cin >> x >> y >> t;
        // 自身和四个方向取最小时间
        star[x][y] = min(star[x][y], t);
        if (x+1 <= 350) star[x+1][y] = min(star[x+1][y], t);
        if (x-1 >= 0) star[x-1][y] = min(star[x-1][y], t);
        if (y+1 <= 350) star[x][y+1] = min(star[x][y+1], t);
        if (y-1 >= 0) star[x][y-1] = min(star[x][y-1], t);
    }

    queue<Node> q;
    q.push({0, 0, 0});
    vis[0][0] = true;

    while (!q.empty()) {
        auto [x,y,t] = q.front();
        q.pop();

        // 找到安全点
        if (star[x][y] == INF) {
            cout << t;
            return 0;
        }

        // 四个方向扩展
        for (int i = 0; i < 4; ++i) {
            int nx = x + dx[i], ny = y + dy[i];
            int nt = t + 1;

            // 合法性检查
            if (nx < 0 || ny < 0 || vis[nx][ny]) continue;

            // 时间早于摧毁时间
            if (nt < star[nx][ny]) {
                vis[nx][ny] = true;
                q.push({nx, ny, nt});
            }
        }
    }

    cout << -1; // 无解
    return 0;
}

路障

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

struct Node { int x, y, t; };  // 节点:坐标(x,y)和时间t
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
int zx[2005], zy[2005];       // 存储每个时间点的路障坐标
bool vis[1005][1005];         // 访问标记
bool mp[1005][1005];          // 标记路障位置

bool bfs(int n) {
    queue<Node> q;
    q.push({1, 1, 0});
    vis[1][1] = true;

    while (!q.empty()) {
        auto [x,y,t] = q.front(); q.pop();

        // 到达终点
        if (x == n && y == n) return true;

        // 放置当前时间对应的路障(注意数组索引可能从1开始)
        if (t >= 1) mp[zx[t-1]][zy[t-1]] = true;  // 假设路障从第1秒开始存储

        // 扩展四个方向
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i], nt = t + 1;
            // 检查合法性:未越界、未被访问、无路障
            if (nx < 1 || ny < 1 || nx > n || ny > n || vis[nx][ny] || mp[nx][ny]) 
                continue;
            vis[nx][ny] = true;
            q.push({nx, ny, nt});
        }
    }
    return false;
}

int main() {
    int T; cin >> T;
    while (T--) {
        int n; cin >> n;
        memset(vis, 0, sizeof(vis));
        memset(mp, 0, sizeof(mp));
        // 读入路障数据(假设从第1秒开始)
        for (int i = 1; i <= 2*n-2; i++) 
            cin >> zx[i] >> zy[i];
        cout << (bfs(n) ? "Yes" : "No") << endl;
    }
    return 0;
}

奇怪的电梯

#include <iostream>
#include <queue>
using namespace std;

int n,a,b;
const int N = 205;
int k[N];
bool vis[N];

void bfs()
{
    queue<pair<int,int>> q;
    q.push({a,0});
    vis[a] = true;
    while(!q.empty())
    {
        auto [cur,step] = q.front();
        q.pop();
        if(cur == b)
        {
            cout << step << endl;
            exit(0);
        }
        
        int up = cur + k[cur];
        if(!vis[up] && up <= n)
        {
            q.push({up,step+1});
            vis[up] = true;
        }
        int down = cur - k[cur];
        if(down > 0 && !vis[down])
        {
            q.push({down,step+1});
            vis[down] = true;
        }
    }
    cout << -1 << endl;
}

int main()
{
    cin >> n >> a >> b;
    for(int i = 1;i <= n;++i) cin >> k[i];
    if(a == b) {
        cout << 0;
        return 0;
    }
    bfs();
    return 0;
}

P2298 Mzc和男家丁的游戏 && P1605 迷宫

//P1683 入门
#include <iostream>
#include <queue>
using namespace std;

int W, H, start_x, start_y, cnt = 1;  // 初始计数包含起点
char grid[25][25];
bool visited[25][25] = {false};        // 访问标记数组

// 方向数组:上下左右
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

void bfs() {
    queue<pair<int, int>> q;
    q.push({start_x, start_y});
    visited[start_x][start_y] = true;

    while (!q.empty()) {
        auto [x, y] = q.front();
        q.pop();

        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            // 检查边界、安全性、是否已访问
            if (nx >= 0 && nx < H && ny >= 0 && ny < W &&
                grid[nx][ny] != '#' && !visited[nx][ny]) {
                visited[nx][ny] = true;
                cnt++;
                q.push({nx, ny});
            }
        }
    }
}

int main() {
    cin >> W >> H;
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            cin >> grid[i][j];
            if (grid[i][j] == '@') {
                start_x = i;
                start_y = j;
            }
        }
    }
    bfs();
    cout << cnt << endl;
    return 0;
}


//P2298 Mzc和男家丁的游戏
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

const int N = 2010;
int n, m, sx, sy;
char grid[N][N];
bool vis[N][N];  // 访问标记数组
// 方向数组:上下左右
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

struct Node {
    int x, y, step;
};

int bfs() {
    queue<Node> q;
    q.push({sx, sy, 0});
    vis[sx][sy] = true;

    while (!q.empty()) {
        Node cur = q.front();
        q.pop();

        for (int i = 0; i < 4; ++i) {
            int nx = cur.x + dx[i];
            int ny = cur.y + dy[i];
            int nstep = cur.step + 1;

            // 越界检查
            if (nx < 1 || nx > n || ny < 1 || ny > m) continue;
            
            // 找到目标直接返回步数
            if (grid[nx][ny] == 'd') return nstep;
            
            // 可通行且未访问
            if (grid[nx][ny] == '.' && !vis[nx][ny]) {
                vis[nx][ny] = true;
                q.push({nx, ny, nstep});
            }
        }
    }
    return -1;
}

int main() {
    // 读取输入
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            cin >> grid[i][j];
            if (grid[i][j] == 'm') {
                sx = i;
                sy = j;
            }
        }
    }
    
    // 执行BFS
    int ans = bfs();
    if (ans != -1) cout << ans << endl;
    else cout << "No Way!" << endl;
    
    return 0;
}

P1331 海战 & P1767 家族

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int MAXN = 1005;
char grid[MAXN][MAXN];
bool vis[MAXN][MAXN];
int R, C;

// 方向数组:上下左右
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

// 预处理检查是否存在非法接触
bool hasInvalidContact() {
    for (int i = 0; i < R-1; ++i) {
        for (int j = 0; j < C-1; ++j) {
            int cnt = 0;
            if (grid[i][j] == '#') cnt++;
            if (grid[i+1][j] == '#') cnt++;
            if (grid[i][j+1] == '#') cnt++;
            if (grid[i+1][j+1] == '#') cnt++;
            if (cnt == 3) return true;
        }
    }
    return false;
}

// BFS验证连通块是否为矩形
bool bfs(int x, int y) {
    queue<pair<int, int>> q;
    q.push({x, y});
    vis[x][y] = true;

    int min_x = x, max_x = x;
    int min_y = y, max_y = y;
    int count = 1;

    while (!q.empty()) {
        auto [cx, cy] = q.front();
        q.pop();

        for (int i = 0; i < 4; ++i) {
            int nx = cx + dx[i];
            int ny = cy + dy[i];
            if (nx >= 0 && nx < R && ny >= 0 && ny < C 
                && grid[nx][ny] == '#' && !vis[nx][ny]) {
                vis[nx][ny] = true;
                q.push({nx, ny});
                count++;
                // 更新行列边界
                min_x = min(min_x, nx);
                max_x = max(max_x, nx);
                min_y = min(min_y, ny);
                max_y = max(max_y, ny);
            }
        }
    }

    // 验证是否为矩形
    int area = (max_x - min_x + 1) * (max_y - min_y + 1);
    return area == count;
}

int main() {
    cin >> R >> C;
    for (int i = 0; i < R; ++i) {
        for (int j = 0; j < C; ++j) {
            cin >> grid[i][j];
        }
    }

    // 步骤1:检查非法接触
    if (hasInvalidContact()) {
        cout << "Bad placement.\n";
        return 0;
    }

    // 步骤2:BFS遍历验证矩形性
    int shipCount = 0;
    for (int i = 0; i < R; ++i) {
        for (int j = 0; j < C; ++j) {
            if (grid[i][j] == '#' && !vis[i][j]) {
                if (!bfs(i, j)) { // 发现非矩形连通块
                    cout << "Bad placement.\n";
                    return 0;
                }
                shipCount++;
            }
        }
    }

    cout << "There are " << shipCount << " ships.\n";
    return 0;
}

------------------------------------------------------------------------

全球变暖

#include <iostream>
#include <queue>
using namespace std;

const int N = 1010;
char g[N][N];
bool vis[N][N];
int flag;
int dx[] = {-1,1,0,0};
int dy[] = {0,0,-1,1};
int n;

void bfs(int x,int y)
{
    queue<pair<int,int>> q;
    q.push({x,y});
    vis[x][y] = true;
    while(!q.empty())
    {
        pair<int,int> t = q.front(); q.pop();
        int tx = t.first, ty = t.second;
        if(g[tx-1][ty] == '#' && g[tx+1][ty] == '#' && g[tx][ty-1] == '#' && g[tx][ty+1] == '#') flag = 1;
        for(int i = 0;i < 4;++i)
        {
            int nx = tx + dx[i], ny = ty + dy[i];
            if(nx < 1 || nx > n || ny < 1 || ny > n) continue;
            if(g[nx][ny] == '#' && vis[nx][ny] == false)
            {
                vis[nx][ny] = true;
                q.push({nx,ny});
            }
        }
    }
}

int main()
{
    cin >> n;
    for(int i = 1;i <= n;++i) cin >> (g[i] + 1);
    int ans = 0;
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= n;++j)
        {
            if(g[i][j] == '#' && vis[i][j] == false)
            {
                flag = 0;
                bfs(i,j);
                if(flag == 0) ans++;
            }
        }
    }
    cout << ans << "\n";
    return 0;
}

打开所有的灯(二进制位模拟灯阵,位运算模拟开灯)

#include <iostream>
#include <queue>
#include <set>
using namespace std;

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

bool isValid(int x,int y)
{
    return x >= 0 && x < 3 && y >= 0 && y < 3;
}

int flip(int state,int x,int y)
{
    int pos = 3*x + y;
    state ^= (1 << pos);
    for(int i = 0;i < 4;++i)
    {
        int nx = x + dx[i], ny = y + dy[i];
        if(isValid(nx,ny))
        {
            int npos = 3*nx + ny;
            state ^= (1 << npos);
        }
    }
    return state;
}

int bfs(int start)
{
    queue<pair<int,int>> q;
    set<int> vis;
    q.push({start,0});
    vis.insert(start);
    while(!q.empty())
    {
        int state = q.front().first;
        int steps = q.front().second;
        q.pop();
        
        if(state == (1 << 9) - 1) return steps;
        
        for(int i = 0;i < 3;++i)
        {
            for(int j = 0;j < 3;++j)
            {
                int newState = flip(state,i,j);
                if(vis.find(newState) == vis.end())
                {
                    q.push({newState,steps + 1});
                    vis.insert(newState);
                }
            }
        }
    }
}

int main()
{
    int start = 0;
    for(int i = 0;i < 3;++i)
    {
        for(int j = 0;j < 3;++j)
        {
            int x; cin >> x;
            start |= (x << (i*3 + j));
        }
    }
    int ans = bfs(start);
    cout << ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值