目录

  • 1. AB路线
  • 1. 问题描述
  • 2. 输入格式
  • 3. 输出格式
  • 4. 样例输入
  • 5. 样例输出
  • 6. 样例说明
  • 7. 评测用例规模与约定
  • 8. 原题链接
  • 2. 解题思路
  • 3. AC_Code


1. AB路线

前置知识点:BFS (广度优先搜索)

1. 问题描述

有一个由 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java

由于特殊的原因,小蓝的路线必须先走 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02 个 A 格子、再走 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02 个 B 格子、再走 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02 个 A 格子、再走 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02

请你计算小蓝最少需要走多少步,才能到达右下角方格? 注意路线经过的格子数不必一定是 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02 的倍数,即最后一段 A 或 B 的格子可以不满 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02

例如 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_蓝桥杯_08 时,以下 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_09

AAA
AAAB
AAABBBAAABBB

以下 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_09

ABABAB
ABBBAAABBB
AAABBBBBBBAAA

2. 输入格式

第一行包含三个整数 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_11第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_12第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02

以下 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_11 行,每行包含 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_12

3. 输出格式

一个整数,代表最少步数。如果无法到达右下角,输出 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_c++_16

4. 样例输入

4 4 2 
AAAB 
ABAB 
BBAB 
BAAA

5. 样例输出

8

6. 样例说明

每一步方向如下:下右下右上右下下;路线序列:AABBAABBA。

7. 评测用例规模与约定

对于 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_c++_17 的数据,第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_c++_18

对于另 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_c++_17 的数据,第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_20

对于 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_c++_21 的数据,第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_22第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_23

8. 原题链接

AB路线

2. 解题思路

在着手解决本问题之前,你需要熟悉基础的 BFS 搜索算法,具体内容可以参考这个链接:https://oi-wiki.org/graph/bfs/。

我们所熟知的 BFS 搜索模型常常是在一个迷宫中从左上角出发,目标是到达右下角,可以上下左右移动,但某些位置有陷阱无法通过,我们需要求的是最短到达时间。

这道题目的基本模型与我们熟悉的搜索模型大致相同,它们的共性包括:

  • 都是从左上角出发,目标是到达右下角。
  • 都可以在四个方向进行移动。
  • 每次移动的权值都为 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_24

因此,这道题很有可能可以使用 BFS 来解答。然而,我们还需要注意到它们的差异性:

  • 在常见的模型中,存在无法通过的陷阱,而在这道题目中,没有陷阱,这使得题目在这一点上甚至比常见的模型更简单。
  • 在常见的模型中,除了陷阱,可以随意移动,而在这道题目中,移动受到 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_蓝桥杯_25
  • 在常见的模型中,每个格子只能被访问一次,而在这道题目中,每个格子最多可以被访问 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_26

接下来,我们将重点讨论最后这一点:

在常规的 BFS 算法中,我们会使用一个数组 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_27 来标识某个位置是否已经被访问过。如果该值为 true,则表示该位置已经被访问过,不能再次访问;如果该值为 false,则表示该位置尚未被访问。这种做法是保证 BFS 算法复杂度的关键,因为每个位置最多只会被访问一次。

但在这道题目中,每个位置可能会被访问多次。因为题目规定 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_28 格只能到达 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_28 格,如果想从 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_28 格到达 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_c++_31 格,必须在第 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02 次访问 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_28 格时才能达到,第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_c++_31

这就意味着,每个格子最多可能会被访问 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02 次。假设某个格子 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_36 的字符为 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_37,到达它可能是连续走了 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_38第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_37

由于 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_02 的取值范围不大,我们可以考虑对 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_41 数组进行扩展,定义 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_42 表示连续走过 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_43第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_37 格后是否能到达格子 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_36,如果能,标记为 true,否则标记为 false。因此,对于同一个 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_43,我们最多只会访问一个格子一次。

在进行 BFS 转移过程中,我们需要根据当前连续步数 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_43

  • 如果 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_48,我们只能从当前格子移动到相同字符的格子,然后 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_26 增加 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_24
  • 如果 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_51,我们只能从当前格子移动到不同字符的格子,然后将 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_算法_26 重置为 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_python_24

除此之外,所有步骤与普通的 BFS 算法相同,时间复杂度为 第十四届蓝桥杯国赛 C++ B 组 G 题——AB路线(AC)_java_54

3. AC_Code

  • C++
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1000000007;
const int N = 1010;

int n, m, k;
bool st[N][N][11];
int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};

int main()
{
    ios_base ::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m >> k;
    vector<string> s(n);

    for (int i = 0; i < n; ++i)
    {
        cin >> s[i];
    }

    queue<array<int, 3>> q;
    q.push({0, 0, 1});
    st[0][0][1] = true;

    int ans = 0;
    while (q.size())
    {
        int size = q.size();
        while (size--)
        {
            auto p = q.front();
            q.pop();
            int x = p[0], y = p[1];
            if (x == n - 1 && y == m - 1)
            {
                cout << ans << '\n';
                return 0;
            }
            if (p[2] == k)
            {
                for (int i = 0; i < 4; ++i)
                {
                    int a = x + dx[i], b = y + dy[i];
                    if (a >= 0 && a < n && b >= 0 && b < m && s[a][b] != s[x][y] && !st[a][b][1])
                    {
                        st[a][b][1] = true;
                        q.push({a, b, 1});
                    }
                }
            }
            else
            {
                for (int i = 0; i < 4; ++i)
                {
                    int a = x + dx[i], b = y + dy[i];
                    if (a >= 0 && a < n && b >= 0 && b < m && s[a][b] == s[x][y] && !st[a][b][p[2] + 1])
                    {
                        st[a][b][p[2] + 1] = true;
                        q.push({a, b, p[2] + 1});
                    }
                }
            }
        }
        ans++;
    }

    cout << -1 << '\n';
    return 0;
}
  • Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int N = 1010;
        int n = input.nextInt();
        int m = input.nextInt();
        int k = input.nextInt();
        boolean[][][] st = new boolean[N][N][11];
        int[] dx = {0, 1, 0, -1};
        int[] dy = {-1, 0, 1, 0};
        String[] s = new String[n];
        for (int i = 0; i < n; ++i) {
            s[i] = input.next();
        }
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[]{0, 0, 1});
        st[0][0][1] = true;
        int ans = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            while (size-- > 0) {
                int[] p = q.poll();
                int x = p[0], y = p[1];
                if (x == n - 1 && y == m - 1) {
                    System.out.println(ans);
                    return;
                }
                if (p[2] == k) {
                    for (int i = 0; i < 4; ++i) {
                        int a = x + dx[i], b = y + dy[i];
                        if (a >= 0 && a < n && b >= 0 && b < m && s[a].charAt(b) != s[x].charAt(y) && !st[a][b][1]) {
                            st[a][b][1] = true;
                            q.add(new int[]{a, b, 1});
                        }
                    }
                } else {
                    for (int i = 0; i < 4; ++i) {
                        int a = x + dx[i], b = y + dy[i];
                        if (a >= 0 && a < n && b >= 0 && b < m && s[a].charAt(b) == s[x].charAt(y) && !st[a][b][p[2] + 1]) {
                            st[a][b][p[2] + 1] = true;
                            q.add(new int[]{a, b, p[2] + 1});
                        }
                    }
                }
            }
            ans++;
        }
        System.out.println(-1);
    }
}
  • Python
def slove():
    n, m, k = map(int, input().split())
    s = []
    for _ in range(n):
        s.append(input())
    q = []
    q.append([0, 0, 1])
    st = [[[False] * 11 for _ in range(m)] for _ in range(n)]
    st[0][0][1] = True
    ans = 0

    dx = [0, 1, 0, -1]
    dy = [-1, 0, 1, 0]
    while q:
        size = len(q)
        while size > 0:
            p = q.pop(0)
            size -= 1
            x, y = p[0], p[1]
            if x == n - 1 and y == m - 1:
                print(ans)
                return
            if p[2] == k:
                for i in range(4):
                    a, b = x + dx[i], y + dy[i]
                    if 0 <= a < n and 0 <= b < m and s[a][b] != s[x][y] and not st[a][b][1]:
                        st[a][b][1] = True
                        q.append([a, b, 1])
            else:
                for i in range(4):
                    a, b = x + dx[i], y + dy[i]
                    if 0 <= a < n and 0 <= b < m and s[a][b] == s[x][y] and not st[a][b][p[2] + 1]:
                        st[a][b][p[2] + 1] = True
                        q.append([a, b, p[2] + 1])
        ans += 1
    print(-1)


slove()