例2.8 叠筐- 九度教程第15题
题目:
时间限制:1 秒 内存限制:128 兆 特殊判题:否
题目描述:
把一个个大小差一圈的筐叠上去,使得从上往下看时,边筐花色交错。这个工作现在要让计算机来完成,得看你的了。
输入:
输入是一个个的三元组,分别是,外筐尺寸n(n为满足0<n<80的奇整数),中心花色字符,外筐花色字符,后二者都为ASCII可见字符;
输出:
输出叠在一起的筐图案,中心花色与外筐花色字符从内层起交错相叠,多筐相叠时,最外筐的角总是被打磨掉。叠筐与叠筐之间应有一行间隔。
样例输入:
11 B A
5 @ W
样例输出:
解析:
如此例所示,其输出图形的规律性主要体现在由内而外的各个环上,而这与输出顺序又不太契合(从上至下,从左至右),不容易将该图形存在的规律直接应用到输出当中,所以需要使用刚才所提到的办法——先排版后输出。先用一个二维数组来保存将要输出的字符阵列,并在该数组上首先完成排版。因为没有了输出时从上至下、从左至右的顺序限制,能更加随意的按照自己的需要或者图形的规律来依次输出图形,从而完成题目要求。
利用一个缓存数组来表示将要输出的字符阵列,规定阵列左上角字符坐标为(1,1),阵列右下角字符坐标为(n,n),其它坐标可由此推得。程序按照由最内圈至最外圈的的顺序来完成图形的排列。
在完成每圈排列时都需要注意两个要点:
(1)首先,需要确定该圈左上角的坐标。将以这个坐标为参照点来完成该圈的其它字符位置的确定(当然也可以选用其它点)。观察图形得知,最中间圈的左上角字符坐标为(n / 2 + 1,n / 2 + 1),次中间圈的左上角字符坐标为(n / 2 + 1- 1,n / 2 + 1 - 1),依次类推即可得到图形中每一个圈的参照点。
(2)其次,需要计算该圈每边边长长度。这也较容易得出,中心圈长度为1,次中心圈长度为3,依次类推,外圈总比内圈长度增加2。
大致思路:
用一个二维数组来保存将要输出的字符阵列,在该数组上完成排版,然后输出。具体排版方法按如下思路进行:
首先,明确该圈使用哪一个字符来填充,使用判断循环次数指示变量j的奇偶性来判断当前需要使用的字符,即奇数次循环时(j为奇数)时使用第一个字符,偶数次循环时使用第二个字符。
然后,确定该圈左上角字符的坐标,使用中心坐标(n / 2 + 1,n / 2 + 1)减去当前循环次数指示变量j来确定该圈左上角坐标,即(n / 2 + 1- j,n / 2 + 1 - j)。
接着,计算该圈边长长度,利用初始值为1的循环指示变量i来表示边长长度,并在每次循环结束后加2,代表边长由1开始,每外移一个圈边长长度即加上2。利用变量i所存的值即可对当前圈的四条边进行赋值,对应的坐标已在代码中给出,这里不再列举。
在完成所有圈的编排后,只需按照题目的需要去除四个角的字符,最后将整个输出缓存中的字符阵列输出即可。
注:
1,while(scanf("%d %c %c",&n,&a,&b)==3) //!!!注意此处格式串中必须含有空格
2, if(n!=1) //注意当n不为1时,不需要此步骤
{ //边界数据处理(n==1为边界数据,当n为1时,不需要将四角字符修改成空格)
outPutBuf[1][1]=' '; //!!!注意此处是单引号-字符,不是双引号-字符串
outPutBuf[1][n]=' ';
outPutBuf[n][1]=' ';
outPutBuf[n][n]=' '; //将四角置为空格
}
3,排版题另一种解决思路:当输出图形具有的规律不能或者很难直接应用到输出上时,就应该考虑此例采用的方法—先排版后输出
代码:
#include<stdio.h>
int main()
{
int outPutBuf[82][82]; //用于预排版的输出缓存
char a,b; //输出的两个字符
int n; //叠筐大小
bool firstCase=true; //是否为第一组数据标志,初始值为true
while(scanf("%d %c %c",&n,&a,&b)==3) //!!!注意此处格式串中必须含有空格
{
if(firstCase==true){//若是第一组数据
firstCase=false;//将第一组数据标志标记成false
}else{
printf("\n"); //否则输出换行
}
for(int i=1,j=1;i<=n;i+=2,j++)//从里之外输出每个圈
{
int x=n/2+1,y=x; //最中间圈的左上角字符坐标
x-=j-1;y-=j-1; //计算每个圈左上角的坐标
char c=j%2==1?a:b;//计算当前圈需要使用哪个字符(奇数圈用a,偶数圈用b)
for(int k=1;k<=i;k++) //对当前圈进行赋值
{
outPutBuf[x+k-1][y]=c; //上方
outPutBuf[x][y+k-1]=c; //左方
outPutBuf[x+i-1][y+k-1]=c; //右方(x坐标不变)
outPutBuf[x+k-1][y+i-1]=c; //下方(y坐标不变)
}
}
if(n!=1) //注意当n不为1时,不需要此步骤
{
outPutBuf[1][1]=' '; //!!!注意此处是单引号-字符,不是双引号-字符串
outPutBuf[1][n]=' ';
outPutBuf[n][1]=' ';
outPutBuf[n][n]=' '; //将四角置为空格
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%c",outPutBuf[i][j]);
}
printf("\n");
}
}
return 0;
}
下面是一个测试例子,WOW!