1 条题解

  • 0
    @ 2025-10-29 19:59:59

    题目分析
    本题要求根据字符画形式的正方体堆叠图,反推出每个位置的正方体个数,并计算总正方体数量。字符画遵循固定的绘制规则,且满足遮挡关系。


    算法思路

    核心思想:模式识别 + 高度递推

    关键观察

    • 每个正方体的“顶面”具有固定模式
    • 从底部向上,正方体高度递减
    • 可以利用字符画中的 | 符号判断垂直方向的高度

    算法流程详解

    1. 正方体顶面模板定义

    string Up[3] = {
        "..+---+",
        "./.../.",
        "+---+.."
    };
    

    这个模板匹配单个正方体的顶面视图(去掉背景.后):

    ..+---+
    ./   /|
    +---+ |
    

    2. 顶面检测函数

    bool check(int x, int y) {
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 7; j++)
                if (Up[i][j] != Map[x + i][y + j] && Up[i][j] != '.')
                    return 0;
        return 1;
    }
    

    作用:在位置(x,y)检测是否存在正方体顶面模式,忽略背景字符.

    3. 高度计算函数(递归)

    int get(int x, int y) {
        if (high[x][y])  // 记忆化
            return high[x][y];
        
        if (Map[x + 1][y] == '|')  // 下方有竖线,说明上面还有正方体
            return get(x + 3, y) + 1;
        
        return 0;  // 底部
    }
    

    原理

    • 每个正方体在垂直方向占3行字符高度
    • 遇到|符号说明上方还有正方体
    • 递归向上计数

    4. 主算法流程

    步骤1:输入处理

    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++) {
            do ch = getchar();
            while (ch != '+' && ch != '/' && ch != '|' && ch != '-' && ch != '.' && ch != ' ');
            Map[i][j] = ch;
        }
    

    过滤无关字符,只保留有效图形字符。

    步骤2:逆向扫描识别

    for (int i = r - 1; ~i; i--)      // 从下往上扫描
        for (int j = c - 1; ~j; j--)  // 从右往左扫描
            if (check(i, j)) {        // 发现正方体顶面
                int H = get(i, j + 6); // 计算该位置高度
                ans += H;             // 累加到总数
                
                // 标记顶点位置的高度(记忆化)
                for (int x = 0; x < 3; x++)
                    for (int y = 0; y < 7; y++)
                        if (Up[x][y] == '+')
                            high[i + x][j + y] = H;
            }
    

    扫描顺序的重要性

    • 从下往上:确保底部正方体先被处理
    • 从右往左:利用题目条件 AijAi,j1A_{ij} \le A_{i,j-1}

    关键技术与优化

    1. 记忆化搜索

    if (high[x][y]) return high[x][y];
    

    避免重复计算同一位置的高度。

    2. 顶点标记

    识别到顶面后,标记所有+顶点的高度,供后续查找使用。

    3. 字符过滤

    只关注关键图形字符,忽略背景和空格。

    4. 模板匹配

    使用固定模板精确识别正方体顶面。


    样例验证

    对于样例输入:

    14 17
    ....+---+---+....
    .../   /   /|....
    ..+---+---+ |....
    ./   /|   | +---+
    +---+ |   |/   /|
    |   | +---+---+ |
    |   |/   /|   | +
    +---+---+ |   |/|
    |   |   | +---+ |
    |   |   |/   /| +
    +---+---+---+ |/.
    |   |   |   | +..
    |   |   |   |/...
    +---+---+---+....
    

    算法过程:

    1. 从底部向上扫描,识别各个顶面位置
    2. 对每个顶面,递归计算下方正方体个数
    3. 累加得到总数:3+3+3+2+2+1=14

    输出:14


    复杂度分析

    • 时间复杂度O(r×c×21)O(r \times c \times 21)
      (每个位置最多检查3×7=21个字符)
    • 空间复杂度O(r×c)O(r \times c)
      对于 r,c1000r,c \leq 1000 的数据范围完全可行

    算法优势

    1. 准确性:基于固定模板匹配,识别精确
    2. 高效性:记忆化避免重复计算
    3. 简洁性:核心逻辑清晰,代码量少
    4. 鲁棒性:适应各种堆叠情况

    该算法巧妙利用字符画的规律性,通过模式识别和递推计算,高效解决了从二维字符画反推三维堆叠的问题。

    • 1

    信息

    ID
    4657
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者