bfs 问题 H: 池塘晨练(dance)

该问题是一个基于网格的路径规划问题,主角贝西在长方形池塘的莲花之间跳跃,其移动方式类似象棋马步。目标是通过广度优先搜索(BFS)算法,找到从起点到终点的最短路径,确保在跳跃过程中不落水或碰到岩石。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有一个美丽的池塘。这个长方形的池子被分成了 M 行 N 列个方格(1≤M,N≤30)。一些格子是坚固得令人惊讶的莲花,还有一些格子是岩石,其余的只是美丽、纯净、湛蓝的水。
贝西正在练习芭蕾舞,她站在一朵莲花上,想跳到另一朵莲花上去,她只能从一朵莲花跳到另一朵莲花上,既不能跳到水里,也不能跳到岩石上。 贝西的舞步很像象棋中的马步:
每次总是先横向移动 M1 (1≤M1≤30)格,再纵向移动 M2 (1≤M2≤30,M1≠M2)格,或先纵向移动 M1 格,再横向移动 M2 格。最多时,贝西会有八个移动方向可供选择。
给定池塘的布局和贝西的跳跃长度,请计算贝西从起点出发,到达目的地的跳的最小舞步数,保证输入数据中的目的地一定是可达的。

输入

第一行:四个用空格分开的整数:M,N,M1 和 M2
第二行到 M+1 行:第 i+1 行有 N 个用空格分开的整数,描述了池塘第 i 行的状态:0 为水,
1 为莲花,2 为岩石,3 为贝西所在的起点,4 为贝西想去的终点

输出

第一行:从起点跳到终点的最少舞步数

样例输入

4 5 1 2
1 0 1 0 1
3 0 2 0 4
0 1 2 0 0
0 0 0 1 0

样例输出

2

无法用方向数组,8种情况依此讨论

#include<bits/stdc++.h>
using namespace std;
int m, n, m1, m2;
int a[33][33] = {};
int vis[33][33] = {};
int sx, sy, lx, ly;
struct node
{
    int x;
    int y;
    int count;
} f, g;

int bfs(int sx, int sy)
{
    queue<node> q;
    f.x = sx;
    f.y = sy;
    f.count = 0;
    q.push(f);
    vis[sx][sy]=1;

    while (!q.empty()) {
        f = q.front();
        q.pop();
        if (f.x == lx && f.y == ly) {
            return f.count;
            break;
        }

        if (f.x + m1 <= m && f.y + m2 <= n && vis[f.x + m1][f.y + m2] == 0 && a[f.x + m1][f.y + m2] == 1)
        {
            g.x = f.x + m1;
            g.y = f.y + m2;
            g.count = f.count+ 1;
            q.push(g);
            vis[g.x][g.y] = 1;  
        }
        if (f.x - m1 > 0 && f.y - m2 > 0 && vis[f.x - m1][f.y - m2] == 0 && a[f.x - m1][f.y - m2] == 1)
        {
            g.x = f.x - m1;
            g.y = f.y - m2;
            g.count = f.count + 1;
            q.push(g);
            vis[g.x][g.y] = 1;
        }
        if (f.x + m1 <= m && f.y - m2 >0 && vis[f.x + m1][f.y - m2] == 0 && a[f.x + m1][f.y - m2] == 1)
        {
            g.x = f.x + m1;
            g.y = f.y - m2;
            g.count = f.count + 1;
            q.push(g);
            vis[g.x][g.y] = 1;
        }
        if (f.x - m1 >0 && f.y + m2 <= n && vis[f.x - m1][f.y + m2] == 0 && a[f.x - m1][f.y + m2] == 1)
        {
            g.x = f.x - m1;
            g.y = f.y + m2;
            g.count = f.count + 1;
            q.push(g);
            vis[g.x][g.y] = 1;
        }
        if (f.x + m2 <= m && f.y + m1 <= n && vis[f.x + m2][f.y + m1] == 0 && a[f.x + m2][f.y + m1] == 1)
        {
            g.x = f.x + m2;
            g.y = f.y + m1;
            g.count = f.count + 1;
            q.push(g);
            vis[g.x][g.y] = 1;
        }
        if (f.x - m2 >0 && f.y - m1 >0 && vis[f.x - m2][f.y - m1] == 0 && a[f.x - m2][f.y - m1] == 1)
        {
            g.x = f.x - m2;
            g.y = f.y - m1;
            g.count = f.count + 1;
            q.push(g);
            vis[g.x][g.y] = 1;
        }
        if (f.x + m2 <= m && f.y - m1 >0 && vis[f.x + m2][f.y - m1] == 0 && a[f.x + m2][f.y - m1] == 1)
        {
            g.x = f.x + m2;
            g.y = f.y - m1;
            g.count = f.count + 1;
            q.push(g);
            vis[g.x][g.y] = 1;
        }
        if (f.x - m2 >0 && f.y + m1 <= n && vis[f.x - m2][f.y + m1] == 0 && a[f.x - m2][f.y + m1] == 1)
        {
            g.x = f.x - m2;
            g.y = f.y + m1;
            g.count = f.count + 1;
            q.push(g);
            vis[g.x][g.y] = 1;
        }
    }

}
int main()
{
    memset(vis, 0, sizeof(vis));
    cin >> m >> n >> m1 >> m2;
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
        {
            cin >> a[i][j];
            if (a[i][j] == 3)
            {
                sx = i;
                sy = j;
                vis[i][j] = 1;
            }//如果为初始位置,入队,并进行标记
            if (a[i][j] == 4)
            {
                lx = i;
                ly = j;
                a[i][j] = 1;
            } //记录结束位置
        }
    cout << bfs(sx, sy) << endl;//bfs
    return 0;
}

参考:http://t.csdn.cn/j1XSG

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值