例2.8 叠筐 - 九度教程第15题(排版题)

 例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!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

weixin_39450145

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

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

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

打赏作者

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

抵扣说明:

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

余额充值