题目来源:
题目内容:
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
代码实现1(有注释):
//自己写的,运行没问题,但是提交了 超时(for循环太多了)以及有部分用例测试失败(不知道哪里出了问题)
#include <iostream>
using namespace std;
int main(){
int n;cin>>n;
char c;cin>>c;
int k;
//除去沙漏最中心的单个符号之外,设上面和下面都有k层
//n=1+2*(3+3+2*(i-1))/2*i
//n=1+(2*i+4)*i
//n=1+2*i*(i+2)
//i=(n-1)/2
if(n==1){cout<<c<<endl;cout<<1;return 0;
}
for(int i=0;i<n;i++){
if(n<1+2*i*(i+2)){
k=i-1;break;
}
}
int k1=n-(1+2*k*(k+2)) ;
//cout<<k<<endl;//n=19 k=2
for(int i=k-1;i>=0;i--){
for(int j1=0;j1<k-i-1;j1++) cout<<" ";
for(int j=0;j<3+2*((i+1)-1);j++) cout<<c;
for(int j2=0;j2<k-i-1;j2++) cout<<" ";
cout<<endl;
}
for(int i=0;i<k;i++) cout<<" ";
cout<<c;
for(int i=0;i<k;i++) cout<<" ";
cout<<endl;
for(int i=0;i<k;i++){
for(int j1=0;j1<k-i-1;j1++) cout<<" ";
for(int j=0;j<3+2*((i+1)-1);j++) cout<<c;
for(int j2=0;j2<k-i-1;j2++) cout<<" ";
//if(i<k-1)
cout<<endl;
}
cout<<k1;
return 0;
}
代码实现2(柳神的版本):
//思路和我差不多,但是细节上处理的比我好
#include <iostream>
using namespace std;
int main() {
int N, row = 0;
char c;
cin >> N >> c;
for (int i = 0; i < N; i++) {
if ((2 * i * (i + 2) + 1) > N) {
row = i - 1;
break;
}
}
for (int i = row; i >= 1; i--) {
for (int k = row - i; k >= 1; k--) cout << " ";
for (int j = i * 2 + 1; j >= 1; j--) cout << c;
cout << endl;
}
for (int i = 0; i < row; i++) cout << " ";
cout << c << endl;
for (int i = 1; i <= row; i++) {
for (int k = row - i; k >= 1; k--) cout << " ";
for (int j = i * 2 + 1; j >= 1; j--) cout << c;
cout << endl;
}
cout << (N - (2 * row * (row + 2) + 1));
return 0;
}
题目心得:
-
这其实是一道数学问题,等差数列的思想求出 除去沙漏最中心的单个符号之外,设上面和下面都有k层
-
这题用到了很多for循环,因此对每个for循环的边界值选取以及初始和结束值的设置就显得尤为重要。这点代码二处理得很好