E2-7.跳马(BFS)

题目描述

马是象棋(包括中国象棋和国际象棋)中的棋子,走法是每步直一格再斜一格,即先横着或者直者走一格,然后再斜着走一个对角线,可进可退,可越过河界,俗称"马走日"字。

给定 m 行 n 列的棋盘(网格图),棋盘上只有棋子象棋中的棋子“马”,并且每个棋子有等级之分,等级为 k 的马可以跳 1~k 步(走的方式与象棋中“马”的规则一样,不可以超出棋盘位置),问是否能将所有马跳到同一位置,如果存在,输出最少需要的总步数(每匹马的步数相加),不存在则输出-1。

注:允许不同的马在跳的过程中跳到同一位置,坐标为(x,y)的马跳一次可以跳到的坐标为:(x+1, y+2),(x+1, y-2),(x+2, y+1),(x+2, y-1),(x-1, y+2),(x-1, y-2),(x-2, y+1),(x-2, y-1),的格点上,但是不可以超出棋盘范围。

输入描述

第一行输入m,n,代表 m 行 n 列的网格图棋盘(1 ≤ m, n ≤ 25)

接下来输入 m 行 n 列的网格图棋盘,如果第 i 行,第 j 列的元素为 "." ,代表此格点没有棋子,如果为数字 k(1 ≤ k ≤ 9),代表此格点存在等级为 k 的“马”

输出描述

输出最少需要的总步数(每匹马的步数相加),不存在则输出-1。

用例1

输入

3 2
..
2.
..

Copy

输出

0

Copy

说明

只有一匹马,不需要跳动

用例2

输入

3 5
47.48
4744.
7....

Copy

输出

17

 

#include <bits/stdc++.h>
using namespace std;
// #define endl '\n'
#define int long long
#define fastio                        \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL);
#pragma GCC optimize(3)
typedef pair<int, int> pii;
const double pi = acos(-1);
const int M = 2e5 + 10;
const int mod = 1e9 + 7;
const int inf = 1e9 + 5;
const int INF = (1ll << 32);
const int dx[] = {1, 1, 2, 2, -1, -1, -2, -2};
const int dy[] = {2, -2, 1, -1, 2, -2, 1, -1};
int m, n;
bool check(int x, int y)
{
    return x >= 0 && x < m && y >= 0 && y < n;
}
vector<vector<int>> bfs(int startx, int starty, int k)
{
    vector<vector<int>> dist(m, vector<int>(n, INT_MAX));
    dist[startx][starty] = 0;
    queue<pair<int, int>> q;
    q.push({startx, starty});
    while (q.size())
    {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        for (int i = 0; i < 8; i++)
        {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (check(nx, ny) && dist[nx][ny] == INT_MAX)
            {
                dist[nx][ny] = dist[x][y] + 1;
                q.push({nx, ny});
            }
        }
    }
    return dist;
}
void solve()
{
    cin >> m >> n;
    vector<vector<int>> board(m, vector<int>(n, 0));
    vector<pair<int, int>> horses; // 存储每个马的位置
    vector<int> horseLevels;       // 存储每个马的等级
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            char c;
            cin >> c;
            if (c != '.')
            {
                int level = c - '0';
                horses.push_back({i, j});
                horseLevels.push_back(level);
                board[i][j] = level;
            }
        }
    }
    // 获取所有可能的目标位置
    int minTotalSteps = INT_MAX;
    // 对每个目标位置进行尝试
    for (int targetX = 0; targetX < m; targetX++)
    {
        for (int targetY = 0; targetY < n; targetY++)
        {
            int totalSteps = 0;
            bool possible = true;

            // 对每匹马进行 BFS,计算从马的当前位置到目标位置的步数
            for (int i = 0; i < horses.size(); i++)
            {
                int startX = horses[i].first;
                int startY = horses[i].second;
                int k = horseLevels[i];

                vector<vector<int>> dist = bfs(startX, startY, k);

                // 如果目标位置不可达
                if (dist[targetX][targetY] == INT_MAX)
                {
                    possible = false;
                    break;
                }

                totalSteps += dist[targetX][targetY];
            }
            if (possible)
            {
                minTotalSteps = min(minTotalSteps, totalSteps);
            }
        }
    }

    if (minTotalSteps == INT_MAX)
    {
        cout << -1 << endl;
    }
    else
    {
        cout << minTotalSteps << endl;
    }
    return;
}
signed main()
{
    fastio int T = 1;
    // cin >> T;
    //   cout<<fixed<<setprecision(10);
    while (T--)
    {
        solve();
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值