1 条题解

  • 0
    @ 2025-4-18 16:33:08

    问题分析

    我们面临的任务是把一个N×MN×M的矩阵中的每个元素(这些元素代表着立方体的高度)转换成一种ASCII艺术的三维视图。这里每个立方体都有一个固定的表示模式,当多个立方体进行堆叠时,必须遵循从后向前、从右向左的顺序来排列。最终输出的图形需要经过计算,确定其最小的宽度和高度,以便能够完整地展示出所有的立方体,并且要用'.'来填充空白的部分。

    解决思路

    1. 确定输出图形的尺寸:首先要做的是计算出输出图形的宽度和高度。每个立方体的基本单元在水平方向和垂直方向上都有固定的尺寸,而且多个立方体堆叠的情况会对整体的宽度和高度产生影响。
      • 宽度计算:每个立方体在水平方向上占用的字符数是44个(即'+---+'),不过在堆叠时会向右和向前延伸。对于一个NNMM列的矩阵而言,图形最宽的部分处于最前面的行(也就是最后一行)和最右边的列(即第一列)。具体来讲,宽度的计算公式为4M+2N4*M + 2*N
      • 高度计算:每个立方体在垂直方向上占用的字符数是33个(代表高度),但在堆叠时会向上延伸。对于矩阵中每个位置(i,j)(i,j),其对高度的贡献为3A[i][j]3*A[i][j]。然而,整体的高度还得考虑到堆叠的叠加效果,最大高度的计算公式为3maxA+N+M3*max_A + N + M,其中maxAmax_A表示矩阵中元素的最大值。
    2. 构建画布:创建一个大小足够的二维字符数组(即画布),并将其初始状态填充为'.'。
    3. 绘制立方体:按照从后向前(ii00N1N - 1)、从右向左(jjM1M - 100)的顺序来绘制矩阵中每个位置的立方体。对于每一个立方体,都要从下到上绘制它的每一层。
      • 立方体的位置:每个立方体的左下角在画布中的位置需要依据其在矩阵中的位置来计算。具体来说,在行方向上的偏移量为ii,在列方向上的偏移量为2(N1i)+4j2*(N - 1 - i) + 4*j
      • 绘制立方体的每一层:对于每个立方体的每一层(从00A[i][j]1A[i][j] - 1),绘制出其对应的字符。
    4. 输出画布:将画布裁剪到实际使用的部分,然后进行输出。
    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    const string CUBE_TOP =    "+---+";
    const string CUBE_FRONT1 = "|   | +";
    const string CUBE_FRONT2 = "|   |/";
    const string CUBE_SIDE =   "+---+";
    
    void drawCube(vector<string>& canvas, int row, int col, int height) {
        int start_row = (height - 1) * 2;
        
        // Top face
        for (int i = 0; i < 5; i++) {
            if (canvas[start_row][col + i] == '.') {
                canvas[start_row][col + i] = CUBE_TOP[i];
            }
        }
        
        // Front face (upper part)
        for (int i = 0; i < 7; i++) {
            if (canvas[start_row + 1][col + i] == '.') {
                canvas[start_row + 1][col + i] = CUBE_FRONT1[i];
            }
        }
        
        // Front face (lower part)
        for (int i = 0; i < 6; i++) {
            if (canvas[start_row + 2][col + i] == '.') {
                canvas[start_row + 2][col + i] = CUBE_FRONT2[i];
            }
        }
        
        // Side face
        for (int i = 0; i < 5; i++) {
            if (canvas[start_row + 3][col + i] == '.') {
                canvas[start_row + 3][col + i] = CUBE_SIDE[i];
            }
        }
    }
    
    int main() {
        int N, M;
        cin >> N >> M;
        
        vector<vector<int> > A(N, vector<int>(M));
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                cin >> A[i][j];
            }
        }
        
        // Calculate canvas dimensions
        int max_height = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (A[i][j] > max_height) {
                    max_height = A[i][j];
                }
            }
        }
        
        int canvas_rows = max_height * 2 + 2;
        int canvas_cols = M * 4 + N * 2 + 1;
        
        // Initialize canvas with dots
        vector<string> canvas(canvas_rows, string(canvas_cols, '.'));
        
        // Draw cubes from back to front, left to right
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                int base_row = (N - 1 - i) * 2;
                int base_col = j * 4 + (N - 1 - i) * 2;
                
                for (int k = 0; k < A[i][j]; k++) {
                    drawCube(canvas, base_row, base_col, k + 1);
                }
            }
        }
        
        // Find the actual used canvas area
        int first_non_empty_row = 0;
        while (first_non_empty_row < canvas_rows && canvas[first_non_empty_row] == string(canvas_cols, '.')) {
            first_non_empty_row++;
        }
        
        int last_non_empty_row = canvas_rows - 1;
        while (last_non_empty_row >= 0 && canvas[last_non_empty_row] == string(canvas_cols, '.')) {
            last_non_empty_row--;
        }
        
        int first_non_empty_col = canvas_cols;
        int last_non_empty_col = 0;
        for (int i = 0; i < canvas_rows; i++) {
            for (int j = 0; j < canvas_cols; j++) {
                if (canvas[i][j] != '.') {
                    if (j < first_non_empty_col) first_non_empty_col = j;
                    if (j > last_non_empty_col) last_non_empty_col = j;
                }
            }
        }
        
        // Output the result
        for (int i = first_non_empty_row; i <= last_non_empty_row; i++) {
            cout << canvas[i].substr(first_non_empty_col, last_non_empty_col - first_non_empty_col + 1) << endl;
        }
        
        return 0;
    }
    • 1

    信息

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