非常标准的一道思考题。

题目描述

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

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

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

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

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

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

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

这题不需要一定立体几何的分析。

我们都知道透视是什么。透视让你通过二维屏幕yy出三维空间 什么xjb玩意儿。

也就是说,你如果从右前上方看的话(题目方向),右面的(离你近的)会盖住左面的(离你远的),同理高的盖住低的,前面的盖住后面的。

那么可以遵循自底向上,自后向前,自左向右的绘画准则,在虚拟画布mapx[1010][1010]上面打表(数据范围我乱写的)

1.注意横坐标上限只与从顶上看的矩阵大小有关,但是纵坐标上限还与高度以及从顶上看的矩阵长度(矩阵纵坐标最大值)有关

社会我C哥,人狠话不多,不管那么多。

直接倒着填,右下角基准点,初始化为’.’ , 最后统计上限。

int findx()
{
    for (int i=MAXX;i>=0;i--)
    {
        bool flag=false;
        for (int j=1;j<=MAXY;j++) if (mapx[i][j]!=0) flag=true;
        if (!flag) return i;
    }
}

将每个block右下角作为basic point基准点,推一下公式。具体怎么来的,不作解释。

MAXY=1+4*n+2*m;
MAXX=3000;
    
for (int p=1;p<=maxh;p++)
    for (int i=1;i<=m;i++)
        for (int j=1;j<=n;j++) if (h[i][j]>=1)
        {
            fillx(MAXX-(2*(m-i))-(3*(p-1)),MAXY-(4*(n-j))-(2*i));
            h[i][j]--;
        }

然后打个表。打表还不简单。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<iterator>
#include<utility>
using namespace std;

char mapx[100010][510]={0};
int m,n,maxh=0;
int h[55][55]={0};
int MAXX,MAXY;

void fillx(int posx,int posy)
{
    mapx[posx][posy]=mapx[posx][posy-4]=mapx[posx-3][posy]=mapx[posx-3][posy-4]='+'; //前面的+号
    mapx[posx-2][posy+2]=mapx[posx-5][posy+2]=mapx[posx-5][posy-2]='+'; //剩下的侧面和顶面的+号 
    
    for (int i=1;i<=3;i++) mapx[posx][posy-i]=mapx[posx-3][posy-i]=mapx[posx-5][posy+2-i]='-'; //所有的-    
    
    for (int i=1;i<=2;i++) mapx[posx-i][posy]=mapx[posx-i][posy-4]=mapx[posx-2-i][posy+2]='|'; //所有的|
    
    mapx[posx-1][posy+1]=mapx[posx-4][posy+1]=mapx[posx-4][posy-3]='/'; //所有的/
    
    for (int i=1;i<=3;i++) mapx[posx-1][posy-i]=mapx[posx-2][posy-i]=' '; // 前面空格
    mapx[posx-2][posy+1]=mapx[posx-3][posy+1]=' '; //侧面空格
    for (int i=1;i<=3;i++) mapx[posx-4][posy+1-i]=' '; //顶面空格 
}

int findx()
{
    for (int i=MAXX;i>=0;i--)
    {
        bool flag=false;
        for (int j=1;j<=MAXY;j++) if (mapx[i][j]!=0) flag=true;
        if (!flag) return i;
    }
}

int main()
{
    memset(mapx,0,sizeof(mapx));
    scanf("%d%d",&m,&n);
    for (int i=1;i<=m;i++)
        for (int j=1;j<=n;j++)
        {
            scanf("%d",&h[i][j]);
            maxh=max(maxh,h[i][j]);
        }
    
    MAXY=1+4*n+2*m;
    MAXX=3000;
    
    
    for (int p=1;p<=maxh;p++)
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++) if (h[i][j]>=1)
            {
                fillx(MAXX-(2*(m-i))-(3*(p-1)),MAXY-(4*(n-j))-(2*i));
                h[i][j]--;
            }
    
    int upat=findx();
    
    for (int i=upat+1;i<=MAXX;i++)
    {
        for (int j=1;j<=MAXY;j++)
        {
            if (!mapx[i][j]) printf(".");
            else printf("%c",mapx[i][j]);
        }
        printf("\n");
    }
    return 0;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.