自测-1 打印沙漏 (20分)

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

*****
 ***
  *
 ***
*****

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

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

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

输入样例:

19 *

输出样例:

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

解题思路:在OJ上,图形题并不是太多,所以这个题目非常好,因为你不能用print语句直接打印,给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。题眼在这里,输出多少个符号,随意,输出什么符号,随意,有两个随意在这里,我们就要去找行列的数值运算关系,也就是二维中的数量关系,这是一个非常重要的考查点,因为涉及图形学的问题都是从这里起步的,这个题目的难点在哪呢?就是这个沙漏形状,因为我们的作业里一向都是三角形,最多出现菱形,老师都觉得,哎呀,太难了吧,学生不一定会,其实如果你真正掌握了三角形的各个形态怎么处理,菱形就是double一下,只不过double的时候要处理空格问题,这个沙漏和菱形类似,但是它多了一层输出多少个符号的计算,把问题这样想开了之后,首先,你要翻翻看,原来打印三角形时,你都用了什么方法,如果从来没做过这样的题,那你麻烦了,不可能从这个题直接学到有用的东西了,怎么办,先去补基础,把三角形弄稳了,再思考这道题:

*****
 ***
  *
 ***
*****

这个图形,有几个数学上的特点:
1, 每行最大符号号数与行数相等,也就是说,最大行如果是5个符号,那么就有5行,那么给多少符号才能出现7行呢?17+14=31,所以,给的符号数一定是+2*(2n-1),那么这就是判断给的数字能打印几行的数学公式了,还有一个1我们单独处理,因为从数据归纳法中,我们知道,起始状态总是有点点特别的,也正是因为这点特别,递归才能完成,当 n=1时,不需要公式,当n=3时,累加上去就可以了,这时,我们就得到了计算使用多少字符的数学依据,如果你能想到这些,说明计算思维没问题下面就是代码的书写:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
    int row,n,i,z,p,surplus,mid;
    char ch;
    scanf("%d %c",&n,&ch);
    for(row=1;row<=n;row+=2)//算出row(沙漏的行数)和surplus(剩余的图形数)
    {
        if(row==1)//一行的话,剩n-1
            surplus=n-1;
        else
            surplus-=2*row;//
        if(surplus<2*(row+2))
            break;
    }
    mid=row/2+1;//求出中间行
    //row行,最大row
    for(i=1;i<=row;i++)//一次把图形打印
    {
        if(i==1) p=row;//求出第i行对应的图形数
            else
            {
                if(i<mid) p-=2;//中间值以下,由p每次递减2
                if(i>mid) p+=2;//中间值以上,由p每次递增2
                if(i==mid) p=1;//中间值等于1
            }
            for(z=0;z<(row-p)/2;z++)//打印第i行的图形前的空格,(满足行数-i行的图形数)/2
                printf(" ");
            for(z=0;z<p;z++)
                printf("%c",ch);
            printf("\n");
    }
    printf("%d",surplus);//打印剩余的图形数

}

测试结果:
测试结果
第二种方法:
因为我在做题的时候发现了一个规律,最大行的图形数=行数,且如果将其分成两个等差数列的三角形,因为an=2n-1,Sn=n^2,如果给出了图形数,就可以将行数求出来,就直接从上到下打印两遍,一遍:倒三角,用三个for()循环,一个大的用来控制行数,两个小的平行,分别打印空格,字符。二遍:正三角,去掉一个尖,打印出来即可。
最后再用公式求出剩下的图形数=总数-两个等差数列和-1
代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
    int a;
    char m;
    scanf("%d %c",&a,&m);
    int i,j,k;
    int b=sqrt((a+1)/2);//
    int c=2*b-1;
    int d=a-b*(1+c)+1;
    for(i=1;i<=b;i++)
    {
        for(k=1;k<i;k++)
        {
            printf(" ");
        }
        for(j=c-2*(i-1);j>0;j--)
        {
            printf("%c",m);
        }
        printf("\n");

    }
    for(i=1;i<b;i++)
    {
        for(k=b-i-1;k>0;k--)
        {
            printf(" ");
        }

        for(j=2*i+1;j>0;j--)
        {
            printf("%c",m);
        }
        printf("\n");

    }
    printf("%d",d);
    return 0;

}
发布了24 篇原创文章 · 获赞 11 · 访问量 3204

猜你喜欢

转载自blog.csdn.net/qq_44292472/article/details/104426553