0
点赞
收藏
分享

微信扫一扫

【PAT (Basic Level) Practice】——【图形输出】1027 打印沙漏

RIOChing 2022-01-10 阅读 29

文章目录

一【题目难度】

  • 乙级

二【题目编号】

  • 1027 打印沙漏 (20 分)

三【题目描述】

  • 本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
 ***
  *
 ***
*****
  • 所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
  • 给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

四【题目示例】

  • 输入格式:
    输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。

  • 输出格式:
    首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

  • 输入样例:
    19 *

  • 输出样例:

*****
 ***
  *
 ***
*****
2

五【解题思路】

  • 这个题我认为是有难度的,主要是不好确定最终多少个符号需要被打印,但是我们可以注意到沙漏是一个倒三角和一个正三角的组合,其中三角尖是共用的,所以我们可以先打印上面的倒三角,再打印下面的正三角,所以我们需要获取以下三个数据:
    ①:三角形的底边拥有的非空格字符数
    ②:每行非空格字符前面需要输出的空格数
    ③:还剩下多少非空格字符没有使用
  • 首先确定三角形的底边拥有的字符数:设这个数为 x x x,于是一个三角形所有字符和为 1 + 3 + 5 + … … x = ( 1 + x ) 2 4 1+3+5+……x=\frac{(1+x)^2}{4} 1+3+5+x=4(1+x)2个,因此一共需要 ( 1 + x ) 2 2 − 1 \frac{(1+x)^2}{2}-1 2(1+x)21个非空格字符,因为题目要求要使用最多的非空格字符,且使用的总非空格字符数不得超过输入的数字 n n n,因此解不等式 ( 1 + x ) 2 2 − 1 ≤ n \frac{(1+x)^2}{2}-1 \leq n 2(1+x)21n,可解得 x ≤ 2 ( 1 + n ) − 1 x \leq \sqrt{2(1+n)}-1 x2(1+n) 1,又因为 x x x为整数,所以 x = ⌊ 2 ( 1 + n ) ⌋ − 1 x=\lfloor \sqrt{2(1+n)} \rfloor - 1 x=2(1+n) 1,其中 ⌊ x ⌋ \lfloor x\rfloor x表示对 x x x向下取整,又因为要求 x x x为奇数,所以若得到 x x x为偶数需要再 − 1 -1 1
  • 然后确定每行非空格字符前面需要输出的空格数:设某行需要输出 i i i个非空格字符,则它的左侧需要输出的空格数为 x − i 2 \frac{x-i}{2} 2xi,其中 x x x是三角形的底边拥有的非空格字符数,右边就不用输出了,只需要输出左边就可以得到结果
  • 最后确定还剩下多少非空格字符没有使用:因为再①中我们已经得到了总共输出的非空格字符数,所以多余的数即为 n − ( ( 1 + x ) 2 2 − 1 ) n-(\frac{(1+x)^2}{2}-1) n(2(1+x)21)
  • 还有两个需要注意的小点如下:
    ①: s q r t sqrt sqrt函数的参数必须是浮点数,所以需要把里面的数字写成小数形式
    ②:向下取整可以直接使用 i n t int int强制类型转换,也可以使用 m a t h . h math.h math.h头文件下的 f l o o r floor floor函数
  • 得到了所有需要的数据就可以直接输出了,输出没有什么难度,只需要在 f o r for for循环里面逐行打印空格和非空格字符,注意别忘了打印完一行需要换行,最后还需要输出剩下多少非空格字符没有使用

六【最终得分】

  • 20分

七【代码实现】

#include <stdio.h>
#include <math.h>
int main()
{
    int n;
    char key;
    scanf("%d %c",&n,&key);
    int bottom = (int)sqrt(2.0 * (n + 1)) - 1;
    if(bottom % 2 == 0)
    {
        bottom--;
    }
    int used = (bottom + 1) * (bottom + 1) / 2 - 1;
    for(int i = bottom;i>=1;i-=2)
    {
        for(int j = 0;j<(bottom - i) / 2;j++)
        {
            printf(" ");
        }
        for(int j = 0;j<i;j++)
        {
            printf("%c",key);
        }
        printf("\n");
    }
    for(int i = 3;i<=bottom;i+=2)
    {
        for(int j = 0;j<(bottom - i) / 2;j++)
        {
            printf(" ");
        }
        for(int j = 0;j<i;j++)
        {
            printf("%c",key);
        }
        printf("\n");
    }
    printf("%d",n-used);
    return 0;
}

八【提交结果】

在这里插入图片描述

举报

相关推荐

0 条评论