1027 打印沙漏——20分
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大
顺序递增;首尾符号数相等。给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式
输入在一行给出1个正整数N(<=1000)和一个符号,中间以空格分隔。
输出格式
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
| 代码长度限制 | 时间限制 ||内存限制 |
|16 KB | 400 ms | 64 MB |
思路:
①这道题需要用等差数列的知识来推导对要打印的层数,然后再进行输出和剩余字符的计算
②除去中间的单个字符,图形上下是对称的,只看下半部分的话(有a1=3,a2=5,a3=7...),所以层号和每层的字符数之间的关系为an=2n+1
③由a1=3,an=2n+1,根据等差数列前N项和公式Sn=n(a1+an)/2求得此问题中上下两个对称层的Sna=n(n+2),
所以全部字符的数量为2S(n-1)+1=2×n^2-1,但是n并不是层数,真正的层数是2n-1
④推导过程可参考下图,建议大家可以在草稿纸上画个图形对着进行推导,这样更加直观:
a1=3,a2=5,a3=7,a4=9......,an=2n+1
Sna=n(n+2) //除中间一个字符外的上或下半边字符数量的前n项和公式
↓↓↓↓↓↓↓↓↓↓
b1=1+2×0
b2=1+2×3
b3=1+2×(3+5)
b4=1+2×(3+5+7)
......
bn = 1+2×(a1+a2+a3+...+a(n-1)) = 1+2S(n-1)a = 2×n^2-1 //图形中全部字符的数量和半边层数n的关系式
//n在b中所指的半边的层数包括了中间一层,因为bn最小是从1开始的,所以全部的层数为2n-1层
⑤根据公式bn求出可以达到的最大层数,条件是bn不能大于题目中的N(可以使用的字符数量),见代码部分的7~10行,然后求出剩余没用掉的字符数量,剩下的图形输出部分就并不难了
代码:
#include<bits/stdtr1c++.h>
using namespace std;
int main() {
int sum;
char c;
scanf("%d %c", &sum, &c);
int h = 1;
while (2 * h * h - 1 <= sum) h++; //根据公式写出条件来判断出半边的层数
h -= 1;
int len = 2 * h - 1; //len为一共有多少层
int surplus = sum - (2 * h * h - 1); //计算出剩下的字符数量
int up_len = len / 2 + 1, down_len = len / 2; //分别求出上半部分和下半部分的层数
for (int i = up_len, j = 0; i >= 1; i--, j++) {
for (int k = 0; k < j; k++) printf(" ");
for (int k = 0; k < i * 2 - 1; k++) printf("%c", c);
cout << endl;
} //打印上半层(包括中间一点)
for (int i = 2, j = down_len - 1; i <= down_len + 1; i++, j--) {
for (int k = 0; k < j; k++) printf(" ");
for (int k = 0; k < i * 2 - 1; k++) printf("%c", c);
cout << endl;
} //打印下半层
cout << surplus; //输出剩余的字符数量
return 0;
}

浙公网安备 33010602011771号