本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
***** *** * *** *****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
***** *** * *** ***** 2
题解:
想必很多小伙伴刚开始看到这个题目的时候觉得这题很简单,上手很容易,但是当真正思考做起来的时候,发现还是有点无从下手的。所以我现在就讲解一下这题我的思路和解法~
第一部分 分解
首先这个“沙漏”是上下对称的,我们可以先找中间以上有几层(包括中间那一层),找到之后上面的层数之后减一,就是下面的层数。
我们用总数相减法来求上面的层数:
除了第一次(也就是减去中间)是一个,其他都是减去2*i,每减一次,都需要计数。一直往下减,直到x为负数,计数停止。
比如:14 *
这里x为14,第一次x=14-1=13;count=1;
第二次x=13-2x3=7;count=2;
第三次x=7-2x5=-3<0
跳出循环,因为count为2,所以上面有两层。
由于减去第一层和减去多层少个二倍,所以将一层和多层单独来写。
由此思路,代码如下:
int Count(int x) { int flag = 1, count = 1, i = 3; if (x < 7)//一层 return 1; else//多层 { x -= 1;//先减去中间层 while (flag) { x -= 2 * i; if (x >= 0) { flag = 1; count++; } else flag = 0; i += 2; } } return count; }
这里就将上面的层数count求出来了,下面的层数就是count-1;
第二部分:打印
上半面
这里找到层数后,就开始考虑打印了。
打印分为空格和*。这里我用表格来显示各部分各部分之间的联系。
由于只需要打印每一层 * 之前的空格就可以,
表格如下 :
for(j=0;j<count;j++) | 空格个数 |
j=0 | 0 |
j=1 | 1 |
j=2 | 2 |
… | … |
j=n | n |
所以打印空格的代码如下:
for (i = 0; i < count; i++) { for (j = 0; j < i; j++) printf(" "); }
现在我们来考虑打印*的部分,还是老样子,表格如下:
for(j=0;j<count;j++) | * 的个数 |
j=0 | 2*count-1 |
j=1 | 2*(count-1)-1 |
j=2 | 2*(count-2)-1 |
… | … |
j=n | 2*(count-j)-1 |
所以代码如下:
int k = count; for (i = 0; i < count; i++) { for (j = 0; j < 2 * k - 1; j++) { printf("%c", c); } k--; }
好的,到此,沙漏的上半部分就完成了~
下半面
老样子,咱还是先看空格部分,如下图所示
这里我们可以用数学公式,来求出第一层的空格数,下面每一层的空格则只需根据上一层的空格数-1即可。
求第一层的空格数:
第一层空格数=(用最后一层‘ * ’个数-第一层‘ * ’个数)/2
怎么求最后一层‘ * ‘个数呢,用刚刚上面的公式:2*count-1
所以打印空格代码如下:
int l=0; l = count * 2 - 1; l = (l - 3) / 2; for (i = 0; i < count - 1; i++) { for (j = 0; j < l; j++) printf(" "); l -= 1; }
好,打印完下半面空格数,我们来打印下半面的*。这里就很简单,由于第一层的*的个数是3,不变,下一层只需要在原有基础上加2。
所以打印‘ * ’代码如下:
int n = 3; for (i = 0; i < count - 1; i++) { for (j = 0; j < n; j++) { printf("%c", c); } n += 2; }
到此打印就完成了,现在就差输出剩下没用掉的符号数~
输出未用符号数
只需要在打印函数里,对每一次打印*时进行计数即可。
int Printc(int count, char c) { int count1 = 0; for (i = 0; i < count; i++) { for (j = 0; j < 2 * k - 1; j++) { printf("%c", c); count1++; } } for (i = 0; i < count - 1; i++) { for (j = 0; j < n; j++) { printf("%c", c); count1++; } } }
总代码如下:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int Count(int x) { int flag = 1, count = 1, i = 3; if (x < 7) return 1; else { x -= 1; while (flag) { x -= 2 * i; if (x >= 0) { flag = 1; count++; } else flag = 0; i += 2; } } return count; } int Printc(int count,char c) { int i = 0, j = 0, k = 0, l = 0, n = 3; int count1 = 0; l = count * 2 - 1; l = (l - 3) / 2; k = count; for (i = 0; i < count; i++) { for (j = 0; j < i; j++) printf(" "); for (j = 0; j < 2 * k - 1; j++) { printf("%c", c); count1++; } printf("\n"); k--; } for (i = 0; i < count - 1; i++) { for (j = 0; j < l; j++) printf(" "); for (j = 0; j < n; j++) { printf("%c", c); count1++; } printf("\n"); l -= 1; n += 2; } return count1; } int main() { int x = 0, y = 0; char c = 'a'; scanf("%d %c", &x, &c); y = Count(x); int F=Printc(y,c); printf("%d\n", x-F); return 0; }
方法二:
#include<stdio.h> void Print(int line, char c) { int i = 0, j = 0, k = 0, count = line; //打印上层 for (i = 0; i < line; i++) { for (j = 0; j < i; j++) printf(" "); for (k = 0; k < 2 * count - 1; k++) printf("%c", c); count--; printf("\n"); } //打印下层 count = 1; for (i = 0; i < line - 1; i++) { for (j = 1; j < line - i - 1; j++) printf(" "); for (k = 0; k < 2 * count + 1; k++) printf("%c", c); count++; printf("\n"); } } void Count(int* x,int* y) { int n = 0; for (n = 1; 2 * n * n - 1 < *x; n++); *y = *x - 2 * (n - 1) * (n-1)+1; *x = n - 1; } int main() { int x = 0, y = 0; char c ; scanf("%d %c", &x, &c); Count(&x, &y); Print(x, c); printf("%d", y); return 0; }
好啦~今天C语言分享题到此结束,咱们下期再见