P1058

· · 题解

思路

感觉这道题还是有思维含量的。

考虑如何得到一张立体图。

如果从前往后依次放方块是非常困难的。

所以可以从后往前建方块。

然后可以发现前面的其实可以覆盖后面方块的图,左边的可以覆盖右边的,同一个位置上面的可以覆盖下面的。所以从后往前,从左往右,从下往上作图。

具体的,可以从给出的矩阵的左上角开始建,从上往下,从左往右,在对于每一个矩阵中的位置,从下往上堆方块。堆方块时可以设置一个单位正方体的图,从图形的左下角开始,每次将纵坐标向上移动,对于单位方格有实际意义的位置,直接覆盖原来位置的字符即可。

可以用画图软件操作一下。比如这样:

理解了这些之后这题就非常简单了。

但是这样的方式在数组中存储的位置并不确定。

所以可以将作图的其实位置放在数组中间,上下左右给其充分大的空间,再在作图过程中更新打印时图的大小即可。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int num[55][55],u=1e9,d=0,l=1e9,r=0;
char a[4005][4005];//答案数组
char cube[10][10]={"..+---+",
                   "./   /|",
                   "+---+ |",
                   "|   | +",
                   "|   |/.",
                   "+---+.."};//单个方块
void print(int x,int y,int h)//每个二维中同样位置从下往上堆方块
{
    x-=5;
    for(int k=1;k<=h;k++)
    {
        for(int i=0;i<6;i++)
            for(int j=0;j<7;j++)
                if(cube[i][j]!='.')
                    a[x+i][y+j]=cube[i][j];
        x-=3;//打印方块起始位置移动
    }
    u=min(u,x+3);//更新上界
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>num[i][j];
    int x=3000,y=1000;
    for(int i=1;i<=n;i++)
    {
        int y_=y;
        for(int j=1;j<=m;j++)//从左到右打印
        {
            print(x,y_,num[i][j]);
            y_+=4;
        }
        r=max(r,y_+2);//右界
        x+=2;
        y-=2;
    }
    d=x-2;//下界
    l=y+2;//左界
    for(int i=u;i<=d;i++)
    {
        for(int j=l;j<=r;j++)
        {
            if(!a[i][j])cout<<".";
            else cout<<a[i][j];
        }
        cout<<'\n';
    }
    return 0;
}