打印沙漏

来源:互联网 发布:为mysql设置密码 编辑:程序博客网 时间:2024/05/17 04:24

1.题目描述

自测-1 打印沙漏 (20分)
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
这里写图片描述
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

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

输入格式:

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

输出格式:

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

输入样例:

19 *

输出样例:

这里写图片描述

2.我的解题思路

  • 首先,写出根据行数计算“沙漏”需要用到的符号数目,这里我采用递归的方式实现,从题目示例中很容易看出,“沙漏”符号数目每次相对于上一次增加2*n个符号,其中n代表行数。示例代码如下:
int count(int n){        if (n == 1){            return 1;        } else {            if(n % 2 == 0){                n = n - 1;            }            return count(n - 2) + n * 2;        }}

特别说明:从题目可知,行数为奇数,每行符号数目也为奇数,所以每次递减都是-2。

  • 计算行号,这里用flag表示,确定flag需要用到count函数,当输入符号数N处于count(n - 1)和count(n)之间时,flag=n - 1;同样由于行数时奇数,所以从1开始递增,每次增加2,即flag=n-2;示例代码如下:
for(i = 1; i <= 33; i = i + 2){        if(N == 1){            num = count(1);            flag = 1;            break;        }        if(N >= ((i - 2) * (i - 2)) && N < i * i){            if(N > count((i - 2)) && N < count(i)){                num = count((i - 2));                flag = i - 2;            } else {                num = count(i);                flag = i;            }        }    }    if(flag != 1 && N - num > flag * 2){        for(t = flag; t <= 45; t = t + 2){            if(N > count((t - 2)) && N < count(t)){                num = count((t - 2));                flag = t - 2;                break;            }        }    }

特别说明:num用于记录需要的符号数,因为最后需要打印有多少符号没有使用,即需要打印N-num。
我最开始写的时候没有最下面的if块,导致最大值计算错误。最开始计算思路为:打印格式为方阵,那么符号数目应该在两个相邻flag^2之间,但是二次方增加很快,其中会剩余大部分的符号数目没有使用,不符合题目要求。这也是为什么上一个for循环的终止点在33,因为33^2已经超过题目要求的1000了。
后面的if语句首先判断此时的flag是否能够再添加两层,如果可以,说明此时“沙漏”还不是最大,需要继续判断。里面的for循环用于寻找最大“沙漏”,临界点45是利用count函数计算出来的,此时“沙漏”需要的符号数目正好超过最大值1000,所以取该节点。通过count函数不断对比,找出正确的num和flag。

  • 打印“沙漏”,逐行打印沙漏,首位两行符号数目与flag层数相同,逻辑简单,可以直接if选择出来打印,每打印一行沙漏都需要一个换行符。然后是上半部分沙漏,逐层递减,根据层数增加,左右各向中间缩进,例如:首行是第0行,全部打印;第1行需要从1开始打印符号,前面的打印空格,尾部打印到flag-j处为止。示例代码如下:
for(j = 0; j < flag; j++){        if(j == 0 || j == (flag - 1)){            for(k = 0; k < flag; k++){                printf("%c", c);            }            printf("\n");        } else {            if(j <= ceil(flag / 2)){                for(k = 0; k < (flag - j) ; k++){                    if(k < j){                        printf(" ");                    } else {                        printf("%c", c);                    }                }                printf("\n");            } else {                for(k = 0; k <= j; k++){                    if(k < (flag - 1 - j)){                        printf(" ");                    } else {                        printf("%c", c);                    }                }                printf("\n");            }        }    }    printf("%d", (N - num));

特别说明:最开始提交,一直提示格式错误。后面看了网上其他人的代码发现,沙漏的右半部分并不是打印的空格,到了后面就结束了。红框标出部分不是空格,直接换行了,经过修改,有了上面的代码。
这里写图片描述

参考链接

题目链接
解题参考
解题参考2

最后寄语

写这篇博客,只是记录下自己解题的过程,可能解法缺陷很大,由于代码完成比较仓促,看起来也不是简洁,有很多重复代码。所以附上别人的解题思路给大家参考。最后,一家之言,欢迎拍砖

1 0