[NOIP2008 普及组] 立体图(含代码)

[NOIP2008 普及组] 立体图

题目描述

小渊是个聪明的孩子,他经常会给周围的小朋友们讲些自己认为有趣的内容。最近,他准备给小朋友们讲解立体图,请你帮他画出立体图。

小渊有一块面积为 m × n m \times n m×n 的矩形区域,上面有 m × n m \times n m×n 个边长为 1 1 1 的格子,每个格子上堆了一些同样大小的积木(积木的长宽高都是 1 1 1),小渊想请你打印出这些格子的立体图。我们定义每个积木为如下格式,并且不会做任何翻转旋转,只会严格以这一种形式摆放:

  +---+  /   /| +---+ | 高 |   | + |   |/  宽 +---+   长 \def\arraystretch{1e-10} \begin{aligned} &\verb! +---+!\\ &\verb! / /|!\\ &\verb!+---+ |!\quad\textsf{高}\\ &\verb!| | +!\\ &\verb!| |/ !\quad\textsf{宽}\\ &\verb!+---+ !\\ & \quad\textsf{长} \end{aligned}   +---+ /   /|+---+ ||   | +|   |/ +---+  

每个顶点用 1 1 1 个加号 + 表示,长用 3 3 3- 表示,宽用 1 1 1/,高用两个 | 表示。字符 +-/| 的 ASCII 码分别为 43 43 43 45 45 45 47 47 47 124 124 124。字符 .(ASCII 码 46 46 46)需要作为背景输出,即立体图里的空白部分需要用 . 来代替。立体图的画法如下面的规则:

若两块积木左右相邻,图示为:

..+---+---+ ./   /   /| +---+---+ | |   |   | + |   |   |/. +---+---+.. \def\arraystretch{1e-10} \begin{aligned} \verb!..+---+---+!\\ \verb!./ / /|!\\ \verb!+---+---+ |!\\ \verb!| | | +!\\ \verb!| | |/.!\\ \verb!+---+---+..!\\ \end{aligned} ..+---+---+./   /   /|+---+---+ ||   |   | +|   |   |/.+---+---+..

若两块积木上下相邻,图示为:

..+---+ ./   /| +---+ | |   | + |   |/| +---+ | |   | + |   |/. +---+.. \def\arraystretch{1e-10} \begin{aligned} \verb!..+---+!\\ \verb!./ /|!\\ \verb!+---+ |!\\ \verb!| | +!\\ \verb!| |/|!\\ \verb!+---+ |!\\ \verb!| | +!\\ \verb!| |/.!\\ \verb!+---+..!\\ \end{aligned} ..+---+./   /|+---+ ||   | +|   |/|+---+ ||   | +|   |/.+---+..

若两块积木前后相邻,图示为:

....+---+ .../   /| ..+---+ | ./   /| + +---+ |/. |   | +.. |   |/... +---+.... \def\arraystretch{1e-10} \begin{aligned} \verb!....+---+!\\ \verb!.../ /|!\\ \verb!..+---+ |!\\ \verb!./ /| +!\\ \verb!+---+ |/.!\\ \verb!| | +..!\\ \verb!| |/...!\\ \verb!+---+....!\\ \end{aligned} ....+---+.../   /|..+---+ |./   /| ++---+ |/.|   | +..|   |/...+---+....

立体图中,定义位于第 ( m , 1 ) (m,1) (m,1) 的格子(即第 m m m 行第 1 1 1 列的格子)上面自底向上的第一块积木(即最下面的一块积木)的左下角顶点为整张图最左下角的点。

输入格式

第一行有用空格隔开的 2 2 2个整数 m m m n n n,表示有 m × n m \times n m×n 个格子 ( 1 ≤ m , n ≤ 50 ) (1 \le m,n \le 50) (1m,n50)

接下来的 m m m 行,是一个 m × n m \times n m×n 的矩阵,每行有 n n n 个用空格隔开的整数,其中第 i i i 行第 j j j 列上的整数表示第 i i i 行第 j j j 列的格子上摞有多少个积木($1 \le $ 每个格子上的积木数 $ \le 100$)。

输出格式

输出包含题目要求的立体图,是一个 K K K L L L 列的字符串矩阵,其中 K K K L L L 表示最少需要 K K K L L L 列才能按规定输出立体图。

样例 #1

样例输入 #1

3 4
2 2 1 2
2 2 1 1
3 2 1 2

样例输出 #1

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

题目来源

NOIP2008普及组第四题(洛谷)

题解

#include <iostream>
#include <stdio.h>

using namespace std;

int i, m, n, j, k, l, o, p, a[1001][1001], ma[1001], maxx, maxy;
int z[6] = {2, 1, 0, 0, 0, 0}, s[6] = {6, 6, 6, 6, 5, 4};
char c[1001][1001], c1[10][10] = {
    "  +---+",
    " /   /|",
    "+---+ |",
    "|   | +",
    "|   |/",
    "+---+",
}; // 定义3D积木的模板

// 在画布的 (x, y) 位置画一个立方体
void fg(int x, int y)
{
    int i, j;
    for (i = 5; i >= 0; i--) // 从模板的底部向顶部迭代
        for (j = z[i]; j <= s[i]; j++) // 迭代当前行的宽度
        {
            c[5 - i + x][j + y] = c1[i][j]; // 将模板中的字符放到画布上
            if (5 - i + x > maxx) maxx = 5 - i + x; // 更新最大x坐标
            if (j + y > maxy) maxy = j + y; // 更新最大y坐标
        }
}

int main()
{
    scanf("%d%d", &n, &m); // 输入 n 和 m,分别表示行数和列数
    for (i = 1; i <= n; i++)
        for (j = 0; j < m; j++)
            scanf("%d", &a[i][j]); // 输入每个格子上的积木数

    // 处理每一层的积木
    for (o = 1; o <= n; o++) // 层数循环
        for (k = 0; k < m; k++) // 列循环
            for (l = 0; l < a[o][k]; l++) // 高度循环
                fg((n - o) * 2 + 1 + 3 * l, (n - o) * 2 + 1 + 4 * k); // 计算立方体左下角位置并绘制

    // 输出结果
    for (i = maxx; i >= 1; i--)
    {    
        for (j = 1; j <= maxy; j++)
            if (c[i][j] == '\000') printf("."); // 空白部分用 '.' 填充
            else printf("%c", c[i][j]); // 输出立方体字符
        printf("\n");
    }

    return 0;
}

  • 21
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java 猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值