思路
天啊,不愧是普及组第四题,好难啊,以蒟蒻目前的能力,完全独自的做出来还是力不从心啊,看来以后要加强练习了!!!
我现在处在一种“不看题解就懵逼,一看题解就秒会”的尴尬境界,这么说吧,我理解别人代码的能力远超过我理解我自己代码的能力QAQ......
主要方法是将单个方块的图案存下来(打表万岁),然后找到画布中每个方块的对应坐标,copy即可。
关键在于三点:
- 摆放顺序
显而易见,我们应当从后往前,从下往上,从左往右进行摆放,这样可以处理好遮挡的问题,因为此题的观察视角是右上方(相对于积木而言),如果本题的观察视角改变,处理的顺序也需要改变。 - 坐标的计算
分析完处理顺序后,我们就需要计算画布中方块的对应坐标了。这里不需要找出方块的所有坐标,只需找出某一特殊点(如顶点)即可。怎么计算呢,当然是观察法找规律了。 - 长宽的计算
想要计算出并输出画布,必须求出画布的长与宽,这里可以说是这道题最容易出错的地方了,必须仔细认真。
注:此代码中计算的是左下角的顶点。
Code
#include<cstdio>
#include<iostream>
using namespace std;
const char Stick[6][8]=
{
"..+---+",
"./ /|",
"+---+ |",
"| | +",
"| |/.",
"+---+.."
};
int a[55][55];
char Paint[550][550];//画布
inline void Draw(int x,int y)//涂鸦函数
{
int i,j;
for(i=0;i<6;i++)
for(j=0;j<7;j++)
if(Stick[6-i-1][j]!='.')
Paint[x-i][y+j]=Stick[6-i-1][j];
}
int main()
{
int N,M,K(0),L,i,j,x,y;
scanf("%d%d",&N,&M);
L=4*M+2*N+1;//计算画布宽度
for(i=1;i<=N;i++)
for(j=1;j<=M;j++)
{
scanf("%d",&a[i][j]);
K=max(K,a[i][j]*3+2*(N-i+1)+1);//计算画布长度
}
for(i=1;i<=K;i++)
for(j=1;j<=L;j++)
Paint[i][j]='.';//画布初始化
for(i=1;i<=N;i++)
for(j=1;j<=M;j++)
{
x=K-2*(N-i);
y=2*(N-i)+4*(j-1)+1;//计算坐标
while(a[i][j]--)
{
Draw(x,y);//涂鸦
x-=3;//向上放
}
}
for(i=1;i<=K;i++)
{
for(j=1;j<=L;j++)
printf("%c",Paint[i][j]);
printf("\n");
}//打印画布
return 0;
}