题目
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例
19 *
输出样例
*****
***
*
***
*****
2
思路
沙漏分为上下两个部分,可以看出,每行的符号数都是1、3、5、7...个并且上下对称,最中间一定是一个符号。看测试用例,假如总共有19个符号,用19减去最中间的1,再除以2,(19 - 1) / 2 = 9,即得到上下两半最多各有9个字符。我们只看上半部分,9 - 3 = 6,即中间上面的一行。3是这一行的字符个数,6是剩余的字符个数。再继续向上构建,6 - 5 = 1,5是这一行的字符个数,1是剩余的字符个数。接着,1 - 7 = -6 < 0,结束构建。这里我想到用一个vector容器来存储每行的字符个数。结合while循环便可以求出这个数组。
输出部分:我们需要将沙漏这个图形输出,可以将其拆分成上半部分和下半部分输出,用两个for循环。输出每行,就需要先输出空格,再输出字符。每行空格数目的计算可以用最大字符个数减去每行的字符个数,再除以2。比如测试用例,最大字符个数即为5。
剩下的符号数:需要注意的是,刚开始我们将字符总数减1再除以2,如果字符总数是偶数,就不能被整除。所以算这个剩余数目不能放在刚开始的while循环里,可以在输出的时候,一边输出,一边让总数减去输出数。
代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n;
char c;
cin >> n >> c;
vector<int> sha;
int pos = (n - 1) / 2;//当前符号的总数(单向)
int poss = 1;//当前行符号的个数
sha.push_back(poss);
poss += 2;
int max = 1;//符号数的最大值
int sy = n;//剩余的符号数
while (pos - poss >= 0){
sha.push_back(poss);
max = poss;
pos -= poss;
poss += 2;
}
for (int i = (int)sha.size() - 1; i >= 0; i--){
int cnum = sha[i];//当前行符号的个数
sy -= cnum;
int knum = (max - sha[i]) / 2;//当前行空格的个数
for (int j = 0; j < knum; j++){
cout << " ";
}
for (int j = 0; j < cnum; j++){
cout << c;
}
cout << endl;
}//打印上半部分
for (int i = 1; i < (int)sha.size(); i++){
int cnum = sha[i];
sy -= cnum;
int knum = (max - sha[i]) / 2;
for (int j = 0; j < knum; j++){
cout << " ";
}
for (int j = 0; j < cnum; j++){
cout << c;
}
cout << endl;
}//打印下半部分
cout << sy << endl;
return 0;
}