题解:洛谷 AT_abc437_b Tombola

【题目来源】

洛谷:AT_abc437_b [ABC437B] Tombola - 洛谷

【题目描述】

给定一个有 \(H\)\(W\) 列的网格,每个格子里写有一个互不相同的整数。在第 \(i\) 行第 \(j\) 列的格子里写着整数 \(A_{i,j}\)

现在,主持人依次叫出了 \(N\) 个互不相同的整数 \(B_1, \dots, B_N\)

请统计每一行中,被主持人叫出的整数有多少个,并输出这些行中被叫出整数数量的最大值。

【输入】

输入按如下格式给出:

\(H\) \(W\) \(N\)
\(A_{1,1}\) \(\cdots\) \(A_{1,W}\)
\(\vdots\)
\(A_{H,1}\) \(\cdots\) \(A_{H,W}\)
\(B_1\)
\(\vdots\)
\(B_N\)

【输出】

输出一个整数,表示答案。

【输入样例】

3 4 5
12 3 5 7
6 10 11 9
1 2 4 8
2
4
9
6
11

【输出样例】

3

【核心思想】

  1. 问题分析:给定 \(H \times W\) 的网格,每个格子有一个互不相同的整数。主持人依次叫出 \(N\) 个互不相同的整数,需要统计每一行中被叫出的整数个数,并输出所有行中的最大值。这是一个直接模拟/暴力枚举问题,关键在于逐行逐元素检查是否在被叫出的集合中。

  2. 算法选择

    • 暴力枚举:对于矩阵中的每个元素,遍历 \(B\) 列表检查是否存在匹配
    • 哈希优化(可选):由于数据范围小(\(H, W \le 9\)),直接 \(O(H \cdot W \cdot N)\) 枚举即可通过
  3. 关键步骤

    • 读取输入:读入 \(H, W, N\),网格 \(A[1..H][1..W]\),列表 \(B[1..N]\)
    • 逐行统计(遍历 \(i\)\(1\)\(H\)):
      • 初始化当前行计数器 \(cnt = 0\)
      • 遍历当前行每个元素 \(A_{i,j}\)\(j\)\(1\)\(W\)):
        • 遍历 \(B\) 列表(\(k\)\(1\)\(N\)):
          • \(B_k = A_{i,j}\),则 \(cnt \mathrel{+}= 1\)
      • 更新全局最大值:\(maxn = \max(maxn, cnt)\)
    • 输出 \(maxn\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(H \cdot W \cdot N)\),三重循环枚举
    • 空间复杂度:\(O(H \cdot W + N)\),存储网格和列表
  5. 暴力枚举的核心思想

    • 问题规模决定算法\(H, W \le 9\)\(N \le 9\),总规模极小,无需复杂数据结构
    • 直接映射:将"某数是否被叫出"转化为线性查找,在小数据下比哈希表更简洁
    • 逐行聚合:先统计单行匹配数,再跨行取最大值,分步降低思维复杂度
    • 适用于数据范围极小、规则明确的纯模拟类问题

【算法标签】

入门 #模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 95;  // 最大矩阵大小
int h, w, n;       // h: 行数, w: 列数, n: 数字列表长度
int a[N][N];       // h×w的矩阵
int b[N];          // 包含n个数字的列表

int main()
{
    // 输入矩阵的行数、列数和数字列表长度
    cin >> h >> w >> n;

    // 输入矩阵元素
    for (int i = 1; i <= h; i++)
    {
        for (int j = 1; j <= w; j++)
        {
            cin >> a[i][j];
        }
    }

    // 输入数字列表
    for (int i = 1; i <= n; i++)
    {
        cin >> b[i];
    }

    int maxn = -1e9;  // 初始化最大计数为极小值

    // 遍历每一行
    for (int i = 1; i <= h; i++)
    {
        int cnt = 0;  // 当前行的匹配计数

        // 遍历当前行的每个元素
        for (int j = 1; j <= w; j++)
        {
            // 遍历数字列表中的每个数字
            for (int k = 1; k <= n; k++)
            {
                // 如果矩阵元素等于列表中的数字
                if (b[k] == a[i][j])
                {
                    cnt++;  // 增加计数
                }
            }
        }

        // 更新最大计数
        maxn = max(maxn, cnt);
    }

    // 输出最大计数
    cout << maxn << endl;

    return 0;
}

【运行结果】

3 4 5
12 3 5 7
6 10 11 9
1 2 4 8
2
4
9
6
11
3
posted @ 2026-08-27 11:04  团爸讲算法  阅读(3)  评论(0)    收藏  举报